summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2012-10-19 01:21:22 +0300
committerMarius <mariausol@gmail.com>2012-10-19 01:21:22 +0300
commitc36e19abdfd15bf6cae6fa379c6ce51f3ef5332d (patch)
tree385d8e72bcaf31513b9ae46ec947818648187082
parent69d2352af4b60929b37fc49f3bdb263977016244 (diff)
downloadcontext-c36e19abdfd15bf6cae6fa379c6ce51f3ef5332d.tar.gz
beta 2012.10.19 00:06
-rw-r--r--bibtex/bst/context/cont-ab.bst1
-rw-r--r--bibtex/bst/context/cont-au.bst1
-rw-r--r--bibtex/bst/context/cont-no.bst1
-rw-r--r--bibtex/bst/context/cont-ti.bst1
-rw-r--r--context/data/scite/lexers/data/scite-context-data-context.lua4
-rw-r--r--context/data/scite/lexers/data/scite-context-data-metafun.lua2
-rw-r--r--context/data/scite/lexers/scite-context-lexer-tex.lua12
-rw-r--r--context/data/scite/lexers/scite-context-lexer-txt.lua38
-rw-r--r--context/data/scite/lexers/scite-context-lexer-xml.lua17
-rw-r--r--context/data/scite/lexers/scite-context-lexer.lua47
-rw-r--r--context/data/scite/scite-context-data-context.properties237
-rw-r--r--context/data/scite/scite-context-data-metafun.properties34
-rw-r--r--context/data/scite/scite-context-readme.pdfbin205340 -> 206760 bytes
-rw-r--r--context/data/scite/scite-context-readme.tex2
-rw-r--r--context/data/scite/scite-context.properties16
-rw-r--r--metapost/context/base/metafun.mpiv7
-rw-r--r--metapost/context/base/mp-abck.mpiv2
-rw-r--r--metapost/context/base/mp-apos.mpiv2
-rw-r--r--metapost/context/base/mp-asnc.mpiv2
-rw-r--r--metapost/context/base/mp-butt.mpiv2
-rw-r--r--metapost/context/base/mp-char.mpiv2
-rw-r--r--metapost/context/base/mp-chem.mpiv350
-rw-r--r--metapost/context/base/mp-core.mpiv2
-rw-r--r--metapost/context/base/mp-crop.mpiv14
-rw-r--r--metapost/context/base/mp-figs.mpiv2
-rw-r--r--metapost/context/base/mp-form.mpiv2
-rw-r--r--metapost/context/base/mp-func.mpiv2
-rw-r--r--metapost/context/base/mp-grap.mpiv204
-rw-r--r--metapost/context/base/mp-grid.mpiv2
-rw-r--r--metapost/context/base/mp-grph.mpiv2
-rw-r--r--metapost/context/base/mp-mlib.mpiv29
-rw-r--r--metapost/context/base/mp-page.mpiv2
-rw-r--r--metapost/context/base/mp-shap.mpiv2
-rw-r--r--metapost/context/base/mp-step.mpiv2
-rw-r--r--metapost/context/base/mp-text.mpiv2
-rw-r--r--metapost/context/base/mp-tool.mpiv4
-rw-r--r--scripts/context/lua/mtx-context.lua1518
-rw-r--r--scripts/context/lua/mtx-convert.lua4
-rw-r--r--scripts/context/lua/mtx-epub.lua113
-rw-r--r--scripts/context/lua/mtx-fcd.lua366
-rw-r--r--scripts/context/lua/mtx-flac.lua6
-rw-r--r--scripts/context/lua/mtx-fonts.lua4
-rw-r--r--scripts/context/lua/mtx-grep.lua4
-rw-r--r--scripts/context/lua/mtx-metapost.lua2
-rw-r--r--scripts/context/lua/mtx-pdf.lua142
-rw-r--r--scripts/context/lua/mtx-scite.lua25
-rw-r--r--scripts/context/lua/mtx-server-ctx-help.lua215
-rw-r--r--scripts/context/lua/mtx-server.lua41
-rw-r--r--scripts/context/lua/mtx-tools.lua2
-rw-r--r--scripts/context/lua/mtx-update.lua4
-rw-r--r--scripts/context/lua/mtx-watch.lua11
-rw-r--r--scripts/context/lua/mtxrun.lua2679
-rw-r--r--scripts/context/ruby/fcd_start.rb472
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua2679
-rw-r--r--scripts/context/stubs/unix/mtxrun2679
-rw-r--r--tex/context/base/anch-bar.mkiv150
-rw-r--r--tex/context/base/anch-bck.mkvi14
-rw-r--r--tex/context/base/anch-pgr.lua248
-rw-r--r--tex/context/base/anch-pgr.mkiv120
-rw-r--r--tex/context/base/anch-pos.lua18
-rw-r--r--tex/context/base/anch-pos.mkiv8
-rw-r--r--tex/context/base/anch-tab.mkiv186
-rw-r--r--tex/context/base/attr-col.lua71
-rw-r--r--tex/context/base/attr-eff.lua39
-rw-r--r--tex/context/base/attr-eff.mkiv43
-rw-r--r--tex/context/base/attr-ini.lua36
-rw-r--r--tex/context/base/attr-ini.mkiv12
-rw-r--r--tex/context/base/attr-lay.lua98
-rw-r--r--tex/context/base/attr-lay.mkiv82
-rw-r--r--tex/context/base/attr-neg.lua5
-rw-r--r--tex/context/base/attr-neg.mkiv10
-rw-r--r--tex/context/base/back-exp.lua24
-rw-r--r--tex/context/base/back-exp.mkiv26
-rw-r--r--tex/context/base/back-ini.lua4
-rw-r--r--tex/context/base/back-ini.mkiv6
-rw-r--r--tex/context/base/back-pdf.mkiv28
-rw-r--r--tex/context/base/back-swf.mkiv14
-rw-r--r--tex/context/base/back-u3d.mkiv7
-rw-r--r--tex/context/base/bibl-bib.mkiv2
-rw-r--r--tex/context/base/bibl-tra.lua4
-rw-r--r--tex/context/base/bibl-tra.mkiv25
-rw-r--r--tex/context/base/blob-ini.lua2
-rw-r--r--tex/context/base/buff-ini.lua39
-rw-r--r--tex/context/base/buff-ini.mkiv24
-rw-r--r--tex/context/base/buff-par.lua27
-rw-r--r--tex/context/base/buff-par.mkiv151
-rw-r--r--tex/context/base/buff-par.mkvi131
-rw-r--r--tex/context/base/buff-ver.lua6
-rw-r--r--tex/context/base/buff-ver.mkiv30
-rw-r--r--tex/context/base/catc-ctx.mkiv11
-rw-r--r--tex/context/base/catc-def.mkiv7
-rw-r--r--tex/context/base/catc-ini.lua21
-rw-r--r--tex/context/base/catc-ini.mkiv64
-rw-r--r--tex/context/base/char-cjk.lua23
-rw-r--r--tex/context/base/char-def.lua80
-rw-r--r--tex/context/base/char-enc.lua41
-rw-r--r--tex/context/base/char-ent.lua5
-rw-r--r--tex/context/base/char-ini.lua86
-rw-r--r--tex/context/base/char-map.lua3
-rw-r--r--tex/context/base/char-utf.lua21
-rw-r--r--tex/context/base/chem-ini.lua8
-rw-r--r--tex/context/base/chem-str.lua134
-rw-r--r--tex/context/base/chem-str.mkiv216
-rw-r--r--tex/context/base/cldf-bas.lua52
-rw-r--r--tex/context/base/cldf-com.lua4
-rw-r--r--tex/context/base/cldf-ini.lua26
-rw-r--r--tex/context/base/cldf-int.lua11
-rw-r--r--tex/context/base/cldf-ver.lua6
-rw-r--r--tex/context/base/colo-ext.mkiv10
-rw-r--r--tex/context/base/colo-icc.lua2
-rw-r--r--tex/context/base/colo-ini.lua124
-rw-r--r--tex/context/base/colo-ini.mkiv34
-rw-r--r--tex/context/base/colo-run.lua6
-rw-r--r--tex/context/base/colo-run.mkiv28
-rw-r--r--tex/context/base/cont-log.mkiv10
-rw-r--r--tex/context/base/cont-new.mkii2
-rw-r--r--tex/context/base/cont-new.mkiv497
-rw-r--r--tex/context/base/cont-nop.mkiv22
-rw-r--r--tex/context/base/cont-yes.mkiv80
-rw-r--r--tex/context/base/context-base.lmx4
-rw-r--r--tex/context/base/context-help.lmx1
-rw-r--r--tex/context/base/context-version.pdfbin4128 -> 4140 bytes
-rw-r--r--tex/context/base/context-version.pngbin105721 -> 105499 bytes
-rw-r--r--tex/context/base/context.mkii2
-rw-r--r--tex/context/base/context.mkiv57
-rw-r--r--tex/context/base/context.rme7
-rw-r--r--tex/context/base/context.todo6
-rw-r--r--tex/context/base/core-con.lua153
-rw-r--r--tex/context/base/core-con.mkiv177
-rw-r--r--tex/context/base/core-ctx.ctx23
-rw-r--r--tex/context/base/core-ctx.lua331
-rw-r--r--tex/context/base/core-ctx.mkiv18
-rw-r--r--tex/context/base/core-dat.lua60
-rw-r--r--tex/context/base/core-def.mkiv126
-rw-r--r--tex/context/base/core-env.lua7
-rw-r--r--tex/context/base/core-env.mkiv115
-rw-r--r--tex/context/base/core-fnt.mkiv158
-rw-r--r--tex/context/base/core-ini.mkiv228
-rw-r--r--tex/context/base/core-mis.mkiv738
-rw-r--r--tex/context/base/core-sys.lua90
-rw-r--r--tex/context/base/core-sys.mkiv80
-rw-r--r--tex/context/base/core-two.lua2
-rw-r--r--tex/context/base/core-uti.lua22
-rw-r--r--tex/context/base/core-var.mkiv239
-rw-r--r--tex/context/base/data-env.lua6
-rw-r--r--tex/context/base/data-exp.lua8
-rw-r--r--tex/context/base/data-ini.lua2
-rw-r--r--tex/context/base/data-lua.lua263
-rw-r--r--tex/context/base/data-pre.lua44
-rw-r--r--tex/context/base/data-res.lua59
-rw-r--r--tex/context/base/data-sch.lua68
-rw-r--r--tex/context/base/data-tex.lua7
-rw-r--r--tex/context/base/data-vir.lua8
-rw-r--r--tex/context/base/data-zip.lua16
-rw-r--r--tex/context/base/enco-ini.mkiv111
-rw-r--r--tex/context/base/file-ini.lua5
-rw-r--r--tex/context/base/file-ini.mkvi20
-rw-r--r--tex/context/base/file-job.lua348
-rw-r--r--tex/context/base/file-job.mkvi25
-rw-r--r--tex/context/base/file-lib.lua7
-rw-r--r--tex/context/base/file-mod.lua16
-rw-r--r--tex/context/base/file-res.lua6
-rw-r--r--tex/context/base/file-syn.lua7
-rw-r--r--tex/context/base/font-afk.lua200
-rw-r--r--tex/context/base/font-afm.lua372
-rw-r--r--tex/context/base/font-age.lua1
-rw-r--r--tex/context/base/font-agl.lua2
-rw-r--r--tex/context/base/font-aux.lua2
-rw-r--r--tex/context/base/font-aux.mkvi26
-rw-r--r--tex/context/base/font-chk.lua2
-rw-r--r--tex/context/base/font-chk.mkiv22
-rw-r--r--tex/context/base/font-cid.lua17
-rw-r--r--tex/context/base/font-col.lua96
-rw-r--r--tex/context/base/font-con.lua30
-rw-r--r--tex/context/base/font-ctx.lua272
-rw-r--r--tex/context/base/font-def.lua23
-rw-r--r--tex/context/base/font-ext.lua38
-rw-r--r--tex/context/base/font-fbk.lua23
-rw-r--r--tex/context/base/font-gds.lua59
-rw-r--r--tex/context/base/font-gds.mkvi (renamed from tex/context/base/font-gds.mkiv)4
-rw-r--r--tex/context/base/font-ini.lua24
-rw-r--r--tex/context/base/font-ldr.lua4
-rw-r--r--tex/context/base/font-lib.mkvi4
-rw-r--r--tex/context/base/font-map.lua12
-rw-r--r--tex/context/base/font-mat.mkvi1
-rw-r--r--tex/context/base/font-mis.lua2
-rw-r--r--tex/context/base/font-ota.lua83
-rw-r--r--tex/context/base/font-otb.lua37
-rw-r--r--tex/context/base/font-otc.lua3
-rw-r--r--tex/context/base/font-otd.lua31
-rw-r--r--tex/context/base/font-otf.lua96
-rw-r--r--tex/context/base/font-oti.lua13
-rw-r--r--tex/context/base/font-otn.lua338
-rw-r--r--tex/context/base/font-otp.lua53
-rw-r--r--tex/context/base/font-ott.lua171
-rw-r--r--tex/context/base/font-pat.lua14
-rw-r--r--tex/context/base/font-pre.mkiv30
-rw-r--r--tex/context/base/font-run.mkiv47
-rw-r--r--tex/context/base/font-set.mkvi2
-rw-r--r--tex/context/base/font-sol.lua898
-rw-r--r--tex/context/base/font-sol.mkvi (renamed from tex/context/base/node-spl.mkiv)63
-rw-r--r--tex/context/base/font-sty.mkvi42
-rw-r--r--tex/context/base/font-syn.lua11
-rw-r--r--tex/context/base/font-tfm.lua15
-rw-r--r--tex/context/base/font-tra.mkiv46
-rw-r--r--tex/context/base/font-vf.lua3
-rw-r--r--tex/context/base/grph-epd.lua1
-rw-r--r--tex/context/base/grph-epd.mkiv12
-rw-r--r--tex/context/base/grph-fig.mkiv729
-rw-r--r--tex/context/base/grph-fil.lua11
-rw-r--r--tex/context/base/grph-inc.lua100
-rw-r--r--tex/context/base/grph-inc.mkiv895
-rw-r--r--tex/context/base/grph-raw.lua5
-rw-r--r--tex/context/base/grph-raw.mkiv14
-rw-r--r--tex/context/base/grph-swf.lua15
-rw-r--r--tex/context/base/grph-trf.mkiv492
-rw-r--r--tex/context/base/grph-u3d.lua8
-rw-r--r--tex/context/base/java-ini.lua37
-rw-r--r--tex/context/base/l-boolean.lua45
-rw-r--r--tex/context/base/l-dir.lua18
-rw-r--r--tex/context/base/l-file.lua36
-rw-r--r--tex/context/base/l-io.lua47
-rw-r--r--tex/context/base/l-lpeg.lua228
-rw-r--r--tex/context/base/l-md5.lua33
-rw-r--r--tex/context/base/l-number.lua10
-rw-r--r--tex/context/base/l-os.lua67
-rw-r--r--tex/context/base/l-string.lua17
-rw-r--r--tex/context/base/l-table.lua131
-rw-r--r--tex/context/base/l-unicode.lua356
-rw-r--r--tex/context/base/l-url.lua124
-rw-r--r--tex/context/base/lang-def.lua47
-rw-r--r--tex/context/base/lang-def.mkiv34
-rw-r--r--tex/context/base/lang-frd.mkiv141
-rw-r--r--tex/context/base/lang-frq.mkiv233
-rw-r--r--tex/context/base/lang-ini.lua91
-rw-r--r--tex/context/base/lang-ini.mkiv31
-rw-r--r--tex/context/base/lang-lab.lua67
-rw-r--r--tex/context/base/lang-lab.mkiv70
-rw-r--r--tex/context/base/lang-mis.mkiv31
-rw-r--r--tex/context/base/lang-txt.lua183
-rw-r--r--tex/context/base/lang-url.lua7
-rw-r--r--tex/context/base/lang-wrd.lua97
-rw-r--r--tex/context/base/lpdf-ano.lua6
-rw-r--r--tex/context/base/lpdf-col.lua8
-rw-r--r--tex/context/base/lpdf-epa.lua6
-rw-r--r--tex/context/base/lpdf-epd.lua24
-rw-r--r--tex/context/base/lpdf-fmt.lua40
-rw-r--r--tex/context/base/lpdf-nod.lua71
-rw-r--r--tex/context/base/lpdf-ren.lua120
-rw-r--r--tex/context/base/lpdf-u3d.lua2
-rw-r--r--tex/context/base/luat-bwc.lua2
-rw-r--r--tex/context/base/luat-cbk.lua29
-rw-r--r--tex/context/base/luat-cnf.lua7
-rw-r--r--tex/context/base/luat-cod.lua28
-rw-r--r--tex/context/base/luat-cod.mkiv6
-rw-r--r--tex/context/base/luat-env.lua44
-rw-r--r--tex/context/base/luat-fmt.lua1
-rw-r--r--tex/context/base/luat-ini.lua44
-rw-r--r--tex/context/base/luat-ini.mkiv8
-rw-r--r--tex/context/base/luat-lib.mkiv5
-rw-r--r--tex/context/base/luat-mac.lua92
-rw-r--r--tex/context/base/luat-run.lua12
-rw-r--r--tex/context/base/luat-soc.lua16
-rw-r--r--tex/context/base/luat-sto.lua32
-rw-r--r--tex/context/base/lxml-css.lua48
-rw-r--r--tex/context/base/lxml-ctx.mkiv3
-rw-r--r--tex/context/base/lxml-ini.mkiv4
-rw-r--r--tex/context/base/lxml-lpt.lua51
-rw-r--r--tex/context/base/lxml-tab.lua42
-rw-r--r--tex/context/base/lxml-tex.lua25
-rw-r--r--tex/context/base/m-barcodes.mkiv8
-rw-r--r--tex/context/base/m-chart.lua159
-rw-r--r--tex/context/base/m-chart.mkii2
-rw-r--r--tex/context/base/m-chart.mkvi154
-rw-r--r--tex/context/base/m-database.mkiv7
-rw-r--r--tex/context/base/m-graph.mkiv124
-rw-r--r--tex/context/base/m-ipsum.mkiv198
-rw-r--r--tex/context/base/m-json.mkiv30
-rw-r--r--tex/context/base/m-morse.mkvi12
-rw-r--r--tex/context/base/m-oldfun.mkiv (renamed from tex/context/base/supp-fun.mkiv)44
-rw-r--r--tex/context/base/m-oldnum.mkiv (renamed from tex/context/base/supp-num.mkiv)2
-rw-r--r--tex/context/base/m-pstricks.lua8
-rw-r--r--tex/context/base/m-spreadsheet.lua331
-rw-r--r--tex/context/base/m-spreadsheet.mkiv295
-rw-r--r--tex/context/base/m-timing.mkiv10
-rw-r--r--tex/context/base/m-translate.mkiv27
-rw-r--r--tex/context/base/m-visual.mkiv581
-rw-r--r--tex/context/base/math-act.lua2
-rw-r--r--tex/context/base/math-ali.mkiv101
-rw-r--r--tex/context/base/math-arr.mkiv405
-rw-r--r--tex/context/base/math-def.mkiv10
-rw-r--r--tex/context/base/math-dim.lua6
-rw-r--r--tex/context/base/math-ext.lua5
-rw-r--r--tex/context/base/math-fbk.lua281
-rw-r--r--tex/context/base/math-for.mkiv15
-rw-r--r--tex/context/base/math-ini.lua141
-rw-r--r--tex/context/base/math-ini.mkiv41
-rw-r--r--tex/context/base/math-int.mkiv15
-rw-r--r--tex/context/base/math-noa.lua219
-rw-r--r--tex/context/base/math-ttv.lua799
-rw-r--r--tex/context/base/math-vfu.lua785
-rw-r--r--tex/context/base/meta-grd.mkiv116
-rw-r--r--tex/context/base/meta-imp-dum.mkiv123
-rw-r--r--tex/context/base/meta-ini.lua2
-rw-r--r--tex/context/base/meta-ini.mkiv67
-rw-r--r--tex/context/base/meta-pag.mkiv10
-rw-r--r--tex/context/base/meta-pdf.lua7
-rw-r--r--tex/context/base/meta-pdh.mkiv2
-rw-r--r--tex/context/base/meta-tex.lua2
-rw-r--r--tex/context/base/mlib-ctx.lua2
-rw-r--r--tex/context/base/mlib-pdf.lua93
-rw-r--r--tex/context/base/mlib-pdf.mkiv6
-rw-r--r--tex/context/base/mlib-pps.mkiv16
-rw-r--r--tex/context/base/mlib-run.lua261
-rw-r--r--tex/context/base/mult-aux.lua2
-rw-r--r--tex/context/base/mult-aux.mkiv180
-rw-r--r--tex/context/base/mult-chk.lua5
-rw-r--r--tex/context/base/mult-chk.mkiv14
-rw-r--r--tex/context/base/mult-de.mkii8
-rw-r--r--tex/context/base/mult-def.lua45
-rw-r--r--tex/context/base/mult-def.mkiv76
-rw-r--r--tex/context/base/mult-dim.mkvi1
-rw-r--r--tex/context/base/mult-en.mkii8
-rw-r--r--tex/context/base/mult-fr.mkii8
-rw-r--r--tex/context/base/mult-fun.lua95
-rw-r--r--tex/context/base/mult-ini.lua122
-rw-r--r--tex/context/base/mult-ini.mkiv72
-rw-r--r--tex/context/base/mult-it.mkii8
-rw-r--r--tex/context/base/mult-low.lua50
-rw-r--r--tex/context/base/mult-mes.lua3
-rw-r--r--tex/context/base/mult-nl.mkii8
-rw-r--r--tex/context/base/mult-pe.mkii8
-rw-r--r--tex/context/base/mult-prm.mkiv15
-rw-r--r--tex/context/base/mult-ro.mkii8
-rw-r--r--tex/context/base/mult-sys.mkiv566
-rw-r--r--tex/context/base/node-aux.lua44
-rw-r--r--tex/context/base/node-dir.lua2
-rw-r--r--tex/context/base/node-fin.lua591
-rw-r--r--tex/context/base/node-ini.lua42
-rw-r--r--tex/context/base/node-inj.lua31
-rw-r--r--tex/context/base/node-par.mkiv82
-rw-r--r--tex/context/base/node-ref.lua11
-rw-r--r--tex/context/base/node-res.lua19
-rw-r--r--tex/context/base/node-rul.lua32
-rw-r--r--tex/context/base/node-rul.mkiv40
-rw-r--r--tex/context/base/node-ser.lua27
-rw-r--r--tex/context/base/node-spl.lua619
-rw-r--r--tex/context/base/node-tra.lua90
-rw-r--r--tex/context/base/node-tsk.lua4
-rw-r--r--tex/context/base/node-typ.lua9
-rw-r--r--tex/context/base/norm-ctx.mkiv8
-rw-r--r--tex/context/base/pack-bar.mkiv97
-rw-r--r--tex/context/base/pack-bck.mkvi2
-rw-r--r--tex/context/base/pack-box.mkiv881
-rw-r--r--tex/context/base/pack-com.mkiv14
-rw-r--r--tex/context/base/pack-cut.mkiv163
-rw-r--r--tex/context/base/pack-mrl.mkiv920
-rw-r--r--tex/context/base/pack-obj.lua25
-rw-r--r--tex/context/base/pack-obj.mkiv143
-rw-r--r--tex/context/base/pack-pos.mkiv189
-rw-r--r--tex/context/base/pack-rul.mkiv1021
-rw-r--r--tex/context/base/page-app.mkiv9
-rw-r--r--tex/context/base/page-bck.mkiv394
-rw-r--r--tex/context/base/page-brk.mkiv14
-rw-r--r--tex/context/base/page-col.mkiv245
-rw-r--r--tex/context/base/page-com.mkiv176
-rw-r--r--tex/context/base/page-fac.mkiv48
-rw-r--r--tex/context/base/page-flt.lua14
-rw-r--r--tex/context/base/page-flt.mkiv214
-rw-r--r--tex/context/base/page-flw.mkiv186
-rw-r--r--tex/context/base/page-grd.mkiv6
-rw-r--r--tex/context/base/page-imp.mkiv3
-rw-r--r--tex/context/base/page-inf.mkiv6
-rw-r--r--tex/context/base/page-ini.mkiv46
-rw-r--r--tex/context/base/page-ins.lua97
-rw-r--r--tex/context/base/page-ins.mkiv197
-rw-r--r--tex/context/base/page-lay.mkiv77
-rw-r--r--tex/context/base/page-lin.lua9
-rw-r--r--tex/context/base/page-lin.mkiv597
-rw-r--r--tex/context/base/page-mak.mkvi33
-rw-r--r--tex/context/base/page-mbk.mkvi4
-rw-r--r--tex/context/base/page-mix.lua642
-rw-r--r--tex/context/base/page-mix.mkiv771
-rw-r--r--tex/context/base/page-mul.mkiv2253
-rw-r--r--tex/context/base/page-not.mkiv20
-rw-r--r--tex/context/base/page-one.mkiv259
-rw-r--r--tex/context/base/page-otr.mkvi4
-rw-r--r--tex/context/base/page-par.mkiv88
-rw-r--r--tex/context/base/page-plg.mkiv110
-rw-r--r--tex/context/base/page-pst.lua (renamed from tex/context/base/page-mis.lua)7
-rw-r--r--tex/context/base/page-pst.mkiv (renamed from tex/context/base/page-mis.mkiv)31
-rw-r--r--tex/context/base/page-run.mkiv8
-rw-r--r--tex/context/base/page-sel.mkiv347
-rw-r--r--tex/context/base/page-sel.mkvi368
-rw-r--r--tex/context/base/page-set.mkiv598
-rw-r--r--tex/context/base/page-sid.mkiv60
-rw-r--r--tex/context/base/page-spr.mkiv90
-rw-r--r--tex/context/base/page-str.mkiv39
-rw-r--r--tex/context/base/page-txt.mkvi112
-rw-r--r--tex/context/base/phys-dim.lua66
-rw-r--r--tex/context/base/phys-dim.mkiv19
-rw-r--r--tex/context/base/ppchtex.mkiv18
-rw-r--r--tex/context/base/prop-ini.mkiv2
-rw-r--r--tex/context/base/regi-ini.lua72
-rw-r--r--tex/context/base/s-abr-01.tex554
-rw-r--r--tex/context/base/s-art-01.mkiv4
-rw-r--r--tex/context/base/s-def-01.mkiv2
-rw-r--r--tex/context/base/s-fnt-10.mkiv2
-rw-r--r--tex/context/base/s-fnt-20.mkiv10
-rw-r--r--tex/context/base/s-fnt-28.mkiv2
-rw-r--r--tex/context/base/s-fnt-29.mkiv2
-rw-r--r--tex/context/base/s-fnt-32.mkiv2
-rw-r--r--tex/context/base/s-inf-01.mkvi2
-rw-r--r--tex/context/base/s-inf-03.mkiv117
-rw-r--r--tex/context/base/s-lan-04.mkiv2
-rw-r--r--tex/context/base/s-mod.ctx1
-rw-r--r--tex/context/base/s-pre-60.mkiv134
-rw-r--r--tex/context/base/s-pre-61.tex2
-rw-r--r--tex/context/base/s-pre-62.tex2
-rw-r--r--tex/context/base/s-pre-63.tex1
-rw-r--r--tex/context/base/s-pre-67.tex2
-rw-r--r--tex/context/base/s-pre-69.mkiv2
-rw-r--r--tex/context/base/scrn-fld.lua6
-rw-r--r--tex/context/base/scrn-fld.mkvi10
-rw-r--r--tex/context/base/scrn-ini.lua2
-rw-r--r--tex/context/base/scrn-ini.mkvi14
-rw-r--r--tex/context/base/scrn-pag.mkvi6
-rw-r--r--tex/context/base/scrn-ref.lua2
-rw-r--r--tex/context/base/scrn-wid.lua12
-rw-r--r--tex/context/base/scrn-wid.mkvi125
-rw-r--r--tex/context/base/scrp-cjk.lua3
-rw-r--r--tex/context/base/scrp-ini.lua276
-rw-r--r--tex/context/base/sort-ini.lua2
-rw-r--r--tex/context/base/sort-lan.lua20
-rw-r--r--tex/context/base/spac-ali.lua6
-rw-r--r--tex/context/base/spac-ali.mkiv52
-rw-r--r--tex/context/base/spac-cha.mkiv191
-rw-r--r--tex/context/base/spac-def.mkiv116
-rw-r--r--tex/context/base/spac-grd.mkiv61
-rw-r--r--tex/context/base/spac-hor.mkiv137
-rw-r--r--tex/context/base/spac-par.mkiv7
-rw-r--r--tex/context/base/spac-ver.lua62
-rw-r--r--tex/context/base/spac-ver.mkiv299
-rw-r--r--tex/context/base/status-files.pdfbin24413 -> 24585 bytes
-rw-r--r--tex/context/base/status-lua.pdfbin180149 -> 195620 bytes
-rw-r--r--tex/context/base/status-mkiv.lua7384
-rw-r--r--tex/context/base/status-mkiv.tex308
-rw-r--r--tex/context/base/strc-bkm.mkiv150
-rw-r--r--tex/context/base/strc-blk.lua7
-rw-r--r--tex/context/base/strc-blk.mkiv96
-rw-r--r--tex/context/base/strc-con.mkvi197
-rw-r--r--tex/context/base/strc-def.mkiv59
-rw-r--r--tex/context/base/strc-des.mkii2
-rw-r--r--tex/context/base/strc-des.mkvi52
-rw-r--r--tex/context/base/strc-doc.lua48
-rw-r--r--tex/context/base/strc-doc.mkiv234
-rw-r--r--tex/context/base/strc-enu.mkvi73
-rw-r--r--tex/context/base/strc-flt.mkvi1061
-rw-r--r--tex/context/base/strc-ind.mkiv12
-rw-r--r--tex/context/base/strc-ini.lua25
-rw-r--r--tex/context/base/strc-itm.mkvi89
-rw-r--r--tex/context/base/strc-lab.mkiv241
-rw-r--r--tex/context/base/strc-lnt.mkvi127
-rw-r--r--tex/context/base/strc-lst.lua3
-rw-r--r--tex/context/base/strc-lst.mkvi31
-rw-r--r--tex/context/base/strc-mar.lua11
-rw-r--r--tex/context/base/strc-mat.mkiv488
-rw-r--r--tex/context/base/strc-not.lua180
-rw-r--r--tex/context/base/strc-not.mkvi631
-rw-r--r--tex/context/base/strc-num.lua207
-rw-r--r--tex/context/base/strc-num.mkiv62
-rw-r--r--tex/context/base/strc-pag.lua12
-rw-r--r--tex/context/base/strc-pag.mkiv193
-rw-r--r--tex/context/base/strc-ref.lua127
-rw-r--r--tex/context/base/strc-ref.mkvi346
-rw-r--r--tex/context/base/strc-reg.lua11
-rw-r--r--tex/context/base/strc-reg.mkiv454
-rw-r--r--tex/context/base/strc-ren.mkiv866
-rw-r--r--tex/context/base/strc-sbe.mkiv102
-rw-r--r--tex/context/base/strc-sec.mkiv828
-rw-r--r--tex/context/base/strc-syn.lua2
-rw-r--r--tex/context/base/strc-syn.mkiv4
-rw-r--r--tex/context/base/strc-tag.lua1
-rw-r--r--tex/context/base/strc-tag.mkiv9
-rw-r--r--tex/context/base/supp-ali.mkiv173
-rw-r--r--tex/context/base/supp-box.lua12
-rw-r--r--tex/context/base/supp-box.mkiv68
-rw-r--r--tex/context/base/supp-mat.mkiv143
-rw-r--r--tex/context/base/supp-ran.lua28
-rw-r--r--tex/context/base/supp-ran.mkiv4
-rw-r--r--tex/context/base/supp-vis.mkiv185
-rw-r--r--tex/context/base/symb-run.mkiv8
-rw-r--r--tex/context/base/syst-aux.lua33
-rw-r--r--tex/context/base/syst-aux.mkiv3650
-rw-r--r--tex/context/base/syst-fnt.mkiv2
-rw-r--r--tex/context/base/syst-gen.mkii5
-rw-r--r--tex/context/base/syst-ini.mkiv338
-rw-r--r--tex/context/base/syst-lua.lua52
-rw-r--r--tex/context/base/syst-lua.mkiv7
-rw-r--r--tex/context/base/tabl-ltb.mkiv8
-rw-r--r--tex/context/base/tabl-mis.mkiv288
-rw-r--r--tex/context/base/tabl-ntb.mkiv1912
-rw-r--r--tex/context/base/tabl-nte.mkiv67
-rw-r--r--tex/context/base/tabl-pln.mkiv155
-rw-r--r--tex/context/base/tabl-tab.mkiv174
-rw-r--r--tex/context/base/tabl-tbl.lua6
-rw-r--r--tex/context/base/tabl-tbl.mkiv129
-rw-r--r--tex/context/base/tabl-tsp.mkiv470
-rw-r--r--tex/context/base/tabl-xnt.mkvi2
-rw-r--r--tex/context/base/tabl-xtb.lua5
-rw-r--r--tex/context/base/tabl-xtb.mkvi108
-rw-r--r--tex/context/base/task-ini.lua9
-rw-r--r--tex/context/base/trac-ctx.lua36
-rw-r--r--tex/context/base/trac-ctx.mkiv28
-rw-r--r--tex/context/base/trac-deb.lua13
-rw-r--r--tex/context/base/trac-deb.mkiv6
-rw-r--r--tex/context/base/trac-fil.lua214
-rw-r--r--tex/context/base/trac-inf.lua4
-rw-r--r--tex/context/base/trac-lmx.lua606
-rw-r--r--tex/context/base/trac-set.lua36
-rw-r--r--tex/context/base/trac-tex.lua2
-rw-r--r--tex/context/base/trac-tim.lua2
-rw-r--r--tex/context/base/trac-vis.lua859
-rw-r--r--tex/context/base/trac-vis.mkiv810
-rw-r--r--tex/context/base/type-imp-husayni.mkiv290
-rw-r--r--tex/context/base/type-ini.lua17
-rw-r--r--tex/context/base/type-ini.mkvi14
-rw-r--r--tex/context/base/typo-bld.lua (renamed from tex/context/base/node-par.lua)108
-rw-r--r--tex/context/base/typo-bld.mkiv64
-rw-r--r--tex/context/base/typo-brk.lua17
-rw-r--r--tex/context/base/typo-brk.mkiv18
-rw-r--r--tex/context/base/typo-cap.mkiv44
-rw-r--r--tex/context/base/typo-del.mkiv31
-rw-r--r--tex/context/base/typo-dir.lua10
-rw-r--r--tex/context/base/typo-itm.mkiv273
-rw-r--r--tex/context/base/typo-krn.lua51
-rw-r--r--tex/context/base/typo-krn.mkiv57
-rw-r--r--tex/context/base/typo-mar.lua89
-rw-r--r--tex/context/base/typo-mar.mkiv7
-rw-r--r--tex/context/base/typo-scr.mkiv250
-rw-r--r--tex/context/base/typo-spa.mkiv17
-rw-r--r--tex/context/base/typo-txt.mkvi174
-rw-r--r--tex/context/base/unic-ini.mkiv2
-rw-r--r--tex/context/base/util-deb.lua3
-rw-r--r--tex/context/base/util-dim.lua18
-rw-r--r--tex/context/base/util-jsn.lua145
-rw-r--r--tex/context/base/util-lua.lua213
-rw-r--r--tex/context/base/util-mrg.lua9
-rw-r--r--tex/context/base/util-prs.lua73
-rw-r--r--tex/context/base/util-sql-imp-client.lua253
-rw-r--r--tex/context/base/util-sql-imp-library.lua283
-rw-r--r--tex/context/base/util-sql-imp-swiglib.lua426
-rw-r--r--tex/context/base/util-sql-loggers.lua277
-rw-r--r--tex/context/base/util-sql-sessions.lua349
-rw-r--r--tex/context/base/util-sql-tickets.lua698
-rw-r--r--tex/context/base/util-sql-users.lua391
-rw-r--r--tex/context/base/util-sql.lua425
-rw-r--r--tex/context/base/util-sta.lua342
-rw-r--r--tex/context/base/util-str.lua7
-rw-r--r--tex/context/base/util-tab.lua120
-rw-r--r--tex/context/base/util-tpl.lua117
-rw-r--r--tex/context/base/x-asciimath.mkiv2
-rw-r--r--tex/context/base/x-chemml.lua2
-rw-r--r--tex/context/base/x-chemml.mkiv22
-rw-r--r--tex/context/base/x-dir-05.mkiv4
-rw-r--r--tex/context/base/x-mathml.lua24
-rw-r--r--tex/context/base/x-mathml.mkiv2366
-rw-r--r--tex/context/base/x-udhr.mkiv2
-rw-r--r--tex/context/base/x-xfdf.mkiv72
-rw-r--r--tex/context/base/xtag-ini.mkii50
-rw-r--r--tex/context/base/xtag-pre.mkii13
-rw-r--r--tex/context/fonts/demo.lfg29
-rw-r--r--tex/context/fonts/husayni.lfg6
-rw-r--r--tex/context/interface/keys-cs.xml8
-rw-r--r--tex/context/interface/keys-de.xml8
-rw-r--r--tex/context/interface/keys-en.xml8
-rw-r--r--tex/context/interface/keys-fr.xml8
-rw-r--r--tex/context/interface/keys-it.xml8
-rw-r--r--tex/context/interface/keys-nl.xml8
-rw-r--r--tex/context/interface/keys-pe.xml8
-rw-r--r--tex/context/interface/keys-ro.xml8
-rw-r--r--tex/context/sample/lorem.tex11
-rw-r--r--tex/context/test/pdf-x1a-2001.mkiv2
-rw-r--r--tex/context/test/pdf-x1a-2003.mkiv2
-rw-r--r--tex/context/test/pdf-x3-2002.mkiv2
-rw-r--r--tex/context/test/pdf-x3-2003.mkiv2
-rw-r--r--tex/context/test/pdf-x4.mkiv2
-rw-r--r--tex/context/test/pdf-x4p.mkiv4
-rw-r--r--tex/generic/context/luatex/luatex-basics-gen.lua4
-rw-r--r--tex/generic/context/luatex/luatex-fonts-ext.lua16
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua1892
-rw-r--r--tex/generic/context/luatex/luatex-fonts.lua2
-rw-r--r--tex/generic/context/luatex/luatex-mplib.tex11
593 files changed, 53257 insertions, 32446 deletions
diff --git a/bibtex/bst/context/cont-ab.bst b/bibtex/bst/context/cont-ab.bst
index c524ff8ee..e09da7ca5 100644
--- a/bibtex/bst/context/cont-ab.bst
+++ b/bibtex/bst/context/cont-ab.bst
@@ -618,6 +618,7 @@ FUNCTION {misc}
format.t.title
format.key
"" "\city" address do.out
+ "" "\day" day do.out
"" "\month" month do.out
"" "\pubname" publisher do.out
"" "\howpublished" howpublished do.out
diff --git a/bibtex/bst/context/cont-au.bst b/bibtex/bst/context/cont-au.bst
index 2eba98b0a..d0b87186c 100644
--- a/bibtex/bst/context/cont-au.bst
+++ b/bibtex/bst/context/cont-au.bst
@@ -618,6 +618,7 @@ FUNCTION {misc}
format.t.title
format.key
"" "\city" address do.out
+ "" "\day" day do.out
"" "\month" month do.out
"" "\pubname" publisher do.out
"" "\howpublished" howpublished do.out
diff --git a/bibtex/bst/context/cont-no.bst b/bibtex/bst/context/cont-no.bst
index dbeb8a45d..393d13db8 100644
--- a/bibtex/bst/context/cont-no.bst
+++ b/bibtex/bst/context/cont-no.bst
@@ -618,6 +618,7 @@ FUNCTION {misc}
format.t.title
format.key
"" "\city" address do.out
+ "" "\day" day do.out
"" "\month" month do.out
"" "\pubname" publisher do.out
"" "\howpublished" howpublished do.out
diff --git a/bibtex/bst/context/cont-ti.bst b/bibtex/bst/context/cont-ti.bst
index 734cbb4b6..34175a0ba 100644
--- a/bibtex/bst/context/cont-ti.bst
+++ b/bibtex/bst/context/cont-ti.bst
@@ -618,6 +618,7 @@ FUNCTION {misc}
format.t.title
format.key
"" "\city" address do.out
+ "" "\day" day do.out
"" "\month" month do.out
"" "\pubname" publisher do.out
"" "\howpublished" howpublished do.out
diff --git a/context/data/scite/lexers/data/scite-context-data-context.lua b/context/data/scite/lexers/data/scite-context-data-context.lua
index aa36277b7..86a817b70 100644
--- a/context/data/scite/lexers/data/scite-context-data-context.lua
+++ b/context/data/scite/lexers/data/scite-context-data-context.lua
@@ -1,4 +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", "startnotext", "stopnotext", "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" },
+ ["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", "zeromuskip", "onemuskip", "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", "startnotext", "stopnotext", "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", "startcontextcode", "stopcontextcode", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "doifelsecommandhandler", "doifnotcommandhandler", "doifcommandhandler", "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", "firstargumentfalse", "firstargumenttrue", "secondargumentfalse", "secondargumenttrue", "thirdargumentfalse", "thirdargumenttrue", "fourthargumentfalse", "fourthargumenttrue", "fifthargumentfalse", "fifthsargumenttrue", "sixthargumentfalse", "sixtsargumenttrue", "doglobal", "dodoglobal", "redoglobal", "resetglobal", "donothing", "dontcomplain", "forgetall", "donetrue", "donefalse", "htdp", "unvoidbox", "hfilll", "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", "availablehsize", "localhsize", "setlocalhsize", "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset", "scratchxposition", "scratchyposition", "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset", "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", "scratchnx", "scratchny", "scratchmx", "scratchmy", "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip", "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", "doifnumber", "doifnotnumber", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", "doifassignmentelse", "docheckassignment", "tracingall", "tracingnone", "loggingall", "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace", "executeifdefined", "singleexpandafter", "doubleexpandafter", "tripleexpandafter", "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces", "wait", "writestatus", "define", "redefine", "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure", "getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", "globallet", "glet", "udef", "ugdef", "uedef", "uxdef", "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter", "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter", "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", "newsignal", "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "modulonumber", "dividenumber", "getfirstcharacter", "doiffirstcharelse", "startnointerference", "stopnointerference", "twodigits", "threedigits", "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight" },
} \ No newline at end of file
diff --git a/context/data/scite/lexers/data/scite-context-data-metafun.lua b/context/data/scite/lexers/data/scite-context-data-metafun.lua
index 749be7663..eac24016c 100644
--- a/context/data/scite/lexers/data/scite-context-data-metafun.lua
+++ b/context/data/scite/lexers/data/scite-context-data-metafun.lua
@@ -1,4 +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" },
+ ["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", "autoalign", "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/context/data/scite/lexers/scite-context-lexer-tex.lua b/context/data/scite/lexers/scite-context-lexer-tex.lua
index 1ff68750f..f59624051 100644
--- a/context/data/scite/lexers/scite-context-lexer-tex.lua
+++ b/context/data/scite/lexers/scite-context-lexer-tex.lua
@@ -128,12 +128,13 @@ local checkedword = context.checkedword
local styleofword = context.styleofword
local setwordlist = context.setwordlist
local validwords = false
+local validminimum = 3
-- % language=uk
local knownpreamble = Cmt(#P("% "), function(input,i,_) -- todo : utfbomb
if i < 10 then
- validwords = false
+ validwords, validminimum = false, 3
local s, e, word = find(input,'^(.+)[\n\r]',i) -- combine with match
if word then
local interface = match(word,"interface=([a-z]+)")
@@ -141,7 +142,7 @@ local knownpreamble = Cmt(#P("% "), function(input,i,_) -- todo : utfbomb
currentcommands = commands[interface] or commands.en or { }
end
local language = match(word,"language=([a-z]+)")
- validwords = language and setwordlist(language)
+ validwords, validminimum = setwordlist(language)
end
end
return false
@@ -224,7 +225,7 @@ local p_unit = P("pt") + P("bp") + P("sp") + P("mm") + P("cm") +
--
-- local p_word = Cmt(iwordpattern, function(_,i,s)
-- if validwords then
--- return checkedword(validwords,s,i)
+-- return checkedword(validwords,validminimum,s,i)
-- else
-- return true, { "text", i }
-- end
@@ -232,7 +233,7 @@ local p_unit = P("pt") + P("bp") + P("sp") + P("mm") + P("cm") +
--
-- So we use this one instead:
-local p_word = Ct( iwordpattern / function(s) return styleofword(validwords,s) end * Cp() ) -- the function can be inlined
+local p_word = Ct( iwordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() ) -- the function can be inlined
----- p_text = (1 - p_grouping - p_special - p_extra - backslash - space + hspace)^1
@@ -389,7 +390,8 @@ local stoplua = P("\\stop") * Cmt(luaenvironment,stopdisplaylua)
local startluacode = token("embedded", startlua)
local stopluacode = #stoplua * token("embedded", stoplua)
-local metafuncall = ( P("reusable") + P("usable") + P("unique") + P("use") ) * ("MPgraphic")
+local metafuncall = ( P("reusable") + P("usable") + P("unique") + P("use") + P("reuse") ) * ("MPgraphic")
+ + P("uniqueMPpagegraphic")
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") )
diff --git a/context/data/scite/lexers/scite-context-lexer-txt.lua b/context/data/scite/lexers/scite-context-lexer-txt.lua
index 012167aeb..4c4742d54 100644
--- a/context/data/scite/lexers/scite-context-lexer-txt.lua
+++ b/context/data/scite/lexers/scite-context-lexer-txt.lua
@@ -13,19 +13,20 @@ 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 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 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 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 validminimum = 3
-- local styleset = context.newstyleset {
-- "default",
@@ -37,12 +38,12 @@ local validwords = false
local p_preamble = Cmt(#(S("#!-%") * P(" ")), function(input,i,_) -- todo: utf bomb
if i == 1 then -- < 10 then
- validwords = false
+ validwords, validminimum = false, 3
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)
+ validwords, validminimum = setwordlist(language)
end
end
end
@@ -52,17 +53,8 @@ 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
+ Ct( wordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() ) -- the function can be inlined
local t_text =
token("default", wordtoken^1)
diff --git a/context/data/scite/lexers/scite-context-lexer-xml.lua b/context/data/scite/lexers/scite-context-lexer-xml.lua
index 34636127f..62cbb2d2c 100644
--- a/context/data/scite/lexers/scite-context-lexer-xml.lua
+++ b/context/data/scite/lexers/scite-context-lexer-xml.lua
@@ -71,7 +71,7 @@ local checkedword = context.checkedword
local styleofword = context.styleofword
local setwordlist = context.setwordlist
local validwords = false
-
+local validminimum = 3
-- <?xml version="1.0" encoding="UTF-8" language="uk" ?>
--
@@ -79,29 +79,20 @@ local validwords = false
local p_preamble = Cmt(#P("<?xml "), function(input,i,_) -- todo: utf bomb
if i < 200 then
- validwords = false
+ validwords, validminimum = false, 3
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)
+ validwords, validminimum = 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
+ Ct( iwordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() ) -- the function can be inlined
local p_rest =
token("default", any)
diff --git a/context/data/scite/lexers/scite-context-lexer.lua b/context/data/scite/lexers/scite-context-lexer.lua
index 2db37e26b..1c9f2cec0 100644
--- a/context/data/scite/lexers/scite-context-lexer.lua
+++ b/context/data/scite/lexers/scite-context-lexer.lua
@@ -210,8 +210,11 @@ function context.exact_match(words,word_chars,case_insensitive)
end
-- spell checking (we can only load lua files)
-
+--
-- return {
+-- min = 3,
+-- max = 40,
+-- n = 12345,
-- words = {
-- ["someword"] = "someword",
-- ["anotherword"] = "Anotherword",
@@ -220,42 +223,30 @@ end
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)
+ return false, 3
+ end
+ local list = lists[tag]
+ if not list then
+ 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
+ list = { words = false, min = 3 }
else
- list = list.words or false
- lists[tag] = list
- return list
+ list.words = list.words or false
+ list.min = list.min or 3
end
+ lists[tag] = list
end
+ return list.words, list.min
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 }
+function context.checkedword(validwords,validminimum,s,i) -- ,limit
+ if not validwords then -- or #s < validminimum then
+ return true, { "text", i } -- { "default", i }
else
-- keys are lower
local word = validwords[s]
@@ -278,8 +269,8 @@ function context.checkedword(validwords,s,i) -- ,limit
end
end
-function context.styleofword(validwords,s) -- ,limit
- if not validwords then
+function context.styleofword(validwords,validminimum,s) -- ,limit
+ if not validwords or #s < validminimum then
return "text"
else
-- keys are lower
diff --git a/context/data/scite/scite-context-data-context.properties b/context/data/scite/scite-context-data-context.properties
index 37a39e1e0..c6a0213cf 100644
--- a/context/data/scite/scite-context-data-context.properties
+++ b/context/data/scite/scite-context-data-context.properties
@@ -2,72 +2,87 @@ 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 \
+starttexcode stoptexcode startcontextcode stopcontextcode doifsetupselse \
+doifsetups doifnotsetups setup setups texsetup \
+xmlsetup luasetup directsetup doifelsecommandhandler doifnotcommandhandler \
+doifcommandhandler 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 \
+newhelp then firstargumentfalse firstargumenttrue secondargumentfalse \
+secondargumenttrue thirdargumentfalse thirdargumenttrue fourthargumentfalse fourthargumenttrue \
+fifthargumentfalse fifthsargumenttrue sixthargumentfalse sixtsargumenttrue doglobal \
+dodoglobal redoglobal resetglobal donothing dontcomplain \
+forgetall donetrue donefalse htdp unvoidbox \
+hfilll 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 availablehsize localhsize setlocalhsize nextbox \
+dowithnextbox dowithnextboxcs dowithnextboxcontent dowithnextboxcontentcs scratchwidth \
+scratchheight scratchdepth scratchoffset scratchdistance scratchhsize \
+scratchvsize scratchxoffset scratchyoffset scratchhoffset scratchvoffset \
+scratchxposition scratchyposition scratchtopoffset scratchbottomoffset scratchleftoffset \
+scratchrightoffset scratchcounterone scratchcountertwo scratchcounterthree scratchdimenone \
+scratchdimentwo scratchdimenthree scratchskipone scratchskiptwo scratchskipthree \
+scratchmuskipone scratchmuskiptwo scratchmuskipthree scratchtoksone scratchtokstwo \
+scratchtoksthree scratchboxone scratchboxtwo scratchboxthree scratchnx \
+scratchny scratchmx scratchmy scratchleftskip scratchrightskip \
+scratchtopskip scratchbottomskip 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 doifnumber \
+doifnotnumber doifcommonelse doifcommon doifnotcommon doifinstring \
+doifnotinstring doifinstringelse doifassignmentelse docheckassignment tracingall \
+tracingnone loggingall removetoks appendtoks prependtoks \
+appendtotoks prependtotoks to endgraf endpar \
+everyendpar reseteverypar finishpar empty null \
+space quad enspace obeyspaces obeylines \
+normalspace executeifdefined singleexpandafter doubleexpandafter tripleexpandafter \
+dontleavehmode removelastspace removeunwantedspaces keepunwantedspaces wait \
+writestatus define redefine setmeasure setemeasure \
+setgmeasure setxmeasure definemeasure freezemeasure measure \
+getvalue setvalue setevalue setgvalue setxvalue \
+letvalue letgvalue resetvalue undefinevalue ignorevalue \
+setuvalue setuevalue setugvalue setuxvalue globallet \
+glet udef ugdef uedef uxdef \
+getparameters geteparameters getgparameters getxparameters forgetparameters \
+copyparameters getdummyparameters dummyparameter directdummyparameter setdummyparameter \
+letdummyparameter usedummystyleandcolor usedummystyleparameter usedummycolorparameter 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 newsignal dosingleempty dodoubleempty \
+dotripleempty doquadrupleempty doquintupleempty dosixtupleempty doseventupleempty \
+dosingleargument dodoubleargument dotripleargument doquadrupleargument doquintupleargument \
+dosixtupleargument doseventupleargument dosinglegroupempty dodoublegroupempty dotriplegroupempty \
doquadruplegroupempty doquintuplegroupempty nopdfcompression maximumpdfcompression normalpdfcompression \
modulonumber dividenumber getfirstcharacter doiffirstcharelse startnointerference \
-stopnointerference strut setstrut strutbox strutht \
-strutdp strutwd begstrut endstrut
+stopnointerference twodigits threedigits strut setstrut \
+strutbox strutht strutdp strutwd struthtdp \
+begstrut endstrut lineheight
keywordclass.context.constants=\
zerocount minusone minustwo plusone \
@@ -76,55 +91,55 @@ 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 startnotext stopnotext 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
+zeroskip zeromuskip onemuskip 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 startnotext stopnotext \
+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/context/data/scite/scite-context-data-metafun.properties b/context/data/scite/scite-context-data-metafun.properties
index e0413b2dd..099f8119b 100644
--- a/context/data/scite/scite-context-data-metafun.properties
+++ b/context/data/scite/scite-context-data-metafun.properties
@@ -33,21 +33,21 @@ 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
+thelabel label autoalign 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/context/data/scite/scite-context-readme.pdf b/context/data/scite/scite-context-readme.pdf
index 32c9628b6..5d5113528 100644
--- a/context/data/scite/scite-context-readme.pdf
+++ b/context/data/scite/scite-context-readme.pdf
Binary files differ
diff --git a/context/data/scite/scite-context-readme.tex b/context/data/scite/scite-context-readme.tex
index 6221d7cde..f687c4fe1 100644
--- a/context/data/scite/scite-context-readme.tex
+++ b/context/data/scite/scite-context-readme.tex
@@ -444,7 +444,7 @@ But probably better is to use the next directive just below the
usual \XML\ marker line:
\starttyping
-<?context-xml-directive editor language uk ?>
+<?context-directive editor language uk ?>
\stoptyping
\subject{Interface selection}
diff --git a/context/data/scite/scite-context.properties b/context/data/scite/scite-context.properties
index 1a4f0f5e8..739967d3c 100644
--- a/context/data/scite/scite-context.properties
+++ b/context/data/scite/scite-context.properties
@@ -56,7 +56,7 @@ textwrapper.length=68
file.patterns.tex=
file.patterns.latex=
-file.patterns.context=*.tex;*.mkii;*.mkiv;*.mkvi;
+file.patterns.context=*.tex;*.mkii;*.mkiv;*.mkvi;*.mkix;*.mkxi;
open.suffix.$(file.patterns.context)=.tex
@@ -73,7 +73,7 @@ lexer.$(file.patterns.example)=xml
# Lua : patterns
-file.patterns.lua=*.lua;*.luc;*.cld;*.tuc;*.luj;*.lum;*.tma;*.lfg
+file.patterns.lua=*.lua;*.luc;*.cld;*.tuc;*.luj;*.lum;*.tma;*.lfg;*.luv;*.lui
open.suffix.$(file.patterns.lua)=.lua
@@ -140,6 +140,8 @@ if PLAT_GTK
# Commands: help info, e:\websites\www.pragma-ade.com\showcase.pdf / todo: manuals
command.help.$(file.patterns.context)=$(name.context.texshow) $(CurrentWord)
+command.help.$(file.patterns.context)=mtxrun --gethelp --url="http://localhost:31415/mtx-server-ctx-help.lua?command=%command%" --command="$(CurrentWord)"
+command.help.$(file.patterns.context)=mtxrun --gethelp --url="http://www.contextgarden.net/Command/%command%" --command="$(CurrentWord)"
command.help.$(file.patterns.example)=
command.help.$(file.patterns.metafun)=
@@ -169,9 +171,9 @@ command.compile.$(file.patterns.example)=$(name.example.xmlcheck) $(FileNameExt)
command.compile.*.fo=$(name.example.xmlcheck) $(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.run) --xml $(FileNameExt)
-command.build.*.fo=$(name.context.run) $(name.flag.pdfopen) --xml --use=foxet $(FileNameExt)
+command.build.$(file.patterns.metafun)=$(name.context.mtxrun) --script context $(name.flag.pdfopen) $(FileNameExt)
+command.build.$(file.patterns.example)=$(name.context.run) --forcexml $(FileNameExt)
+command.build.*.fo=$(name.context.run) $(name.flag.pdfopen) --forcexml --use=foxet $(FileNameExt)
command.build.subsystem.$(file.patterns.context)=1
command.build.subsystem.$(file.patterns.metafun)=1
@@ -560,7 +562,7 @@ filter.metafun=MetaFun|$(file.patterns.metafun)|
lexer.$(file.patterns.metafun)=metapost
command.compile.$(file.patterns.metafun)=
-command.build.$(file.patterns.metafun)=context $(FileNameExt)
+command.build.$(file.patterns.metafun)=$(name.context.mtxrun) --script context $(name.flag.pdfopen) $(FileNameExt)
command.go.$(file.patterns.metafun)=gv $(FileName).1
command.0.$(file.patterns.metafun)=
@@ -664,3 +666,5 @@ fold.margin.colour=#CCCCCC
# testing
#~ cache.layout=
+
+find.command=mtxrun --script grep "$(find.what)" "$(find.files)"
diff --git a/metapost/context/base/metafun.mpiv b/metapost/context/base/metafun.mpiv
index d600764a3..8247c121f 100644
--- a/metapost/context/base/metafun.mpiv
+++ b/metapost/context/base/metafun.mpiv
@@ -11,10 +11,9 @@
%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.
+%D First we input John Hobby's metapost plain file. However, because we want to
+%D prevent dependency problems and in the end even may use a patched version,
+%D we prefer to use a copy.
input "mp-base.mpiv" ;
input "mp-tool.mpiv" ;
diff --git a/metapost/context/base/mp-abck.mpiv b/metapost/context/base/mp-abck.mpiv
index 02fab0337..abd7d8848 100644
--- a/metapost/context/base/mp-abck.mpiv
+++ b/metapost/context/base/mp-abck.mpiv
@@ -5,7 +5,7 @@
%D subtitle=anchored background 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/metapost/context/base/mp-apos.mpiv b/metapost/context/base/mp-apos.mpiv
index f92efc5fd..7b7737754 100644
--- a/metapost/context/base/mp-apos.mpiv
+++ b/metapost/context/base/mp-apos.mpiv
@@ -5,7 +5,7 @@
%D subtitle=anchored background 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/metapost/context/base/mp-asnc.mpiv b/metapost/context/base/mp-asnc.mpiv
index dfd88317c..2626e4d58 100644
--- a/metapost/context/base/mp-asnc.mpiv
+++ b/metapost/context/base/mp-asnc.mpiv
@@ -5,7 +5,7 @@
%D subtitle=anchored background 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/metapost/context/base/mp-butt.mpiv b/metapost/context/base/mp-butt.mpiv
index df7e9e4fd..6f5b90a7e 100644
--- a/metapost/context/base/mp-butt.mpiv
+++ b/metapost/context/base/mp-butt.mpiv
@@ -5,7 +5,7 @@
%D subtitle=buttons,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={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/metapost/context/base/mp-char.mpiv b/metapost/context/base/mp-char.mpiv
index c293b7284..f604accd8 100644
--- a/metapost/context/base/mp-char.mpiv
+++ b/metapost/context/base/mp-char.mpiv
@@ -5,7 +5,7 @@
%D subtitle=charts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={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/metapost/context/base/mp-chem.mpiv b/metapost/context/base/mp-chem.mpiv
index cb595f2c6..2b2d8e5bf 100644
--- a/metapost/context/base/mp-chem.mpiv
+++ b/metapost/context/base/mp-chem.mpiv
@@ -3,15 +3,15 @@
%D version=2009.05.13,
%D title=\CONTEXT\ \METAPOST\ graphics,
%D subtitle=chemicals,
-%D author=Hans Hagen,
+%D author=Hans Hagen \& Alan Braslau",
%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 licen-en.pdf for
%C details.
-%D This module in incomplete and experimental.
+%D This module is incomplete and experimental.
% either consistent setting or not
@@ -20,7 +20,7 @@ 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,
+ chem_width, chem_radical_min, chem_radical_max, chem_text_min, chem_text_max, chem_circle_radius,
chem_rotation, chem_adjacent, chem_stack, chem_substituent, chem_direction, chem_setting_scale,
chem_setting_offset, chem_text_offset, chem_picture_offset, chem_center_offset, chem_substituent_offset,
chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b ;
@@ -30,6 +30,9 @@ boolean
chem_setting_fixedwidth, chem_setting_fixedheight,
chem_doing_pb, chem_text_trace ;
+color
+ chem_axis_color ;
+
path
chem_setting_bbox ;
@@ -38,24 +41,26 @@ pair
chem_adjacent_p, chem_substituent_p, chem_direction_p, chem_move_p ;
numeric
- chem_width[], chem_angle[], chem_start[], chem_initialrot[], chem_initialmov[] ;
+ chem_width[], chem_angle[], chem_dbl_offset[], chem_initialmov[] ;
pair
chem_stack_d[],
chem_b_zero[], chem_n_zero[],
- chem_r_max[], chem_r_min[],
+ chem_r_max[],
chem_r_zero[], chem_mr_zero[], chem_pr_zero[], chem_crz_zero[],
chem_rt_zero[], chem_rtt_zero[], chem_rbt_zero[],
+ chem_zbt_zero[], chem_ztt_zero[],
chem_mid_zero[] ;
path
chem_b_path[], chem_bx_path[], chem_eb_path[], chem_sr_path[], chem_br_path[],
chem_sb_path[], chem_msb_path[], chem_psb_path[],
chem_s_path[], chem_ss_path[], chem_mss_path[], chem_pss_path[],
- chem_e_path[], chem_sd_path[], chem_bb_path[], chem_oe_path[],
+ chem_e_path[], chem_bb_path[], chem_oe_path[],
chem_bd_path[], chem_bw_path[],
chem_ddt_path[], chem_ddb_path[], chem_ldt_path[], chem_ldb_path[], chem_rdt_path[], chem_rdb_path[],
chem_dbl_path[], chem_dbr_path[],
+ chem_tbl_path[], chem_tbr_path[],
chem_ad_path[], chem_au_path[],
chem_r_path[], chem_rl_path[], chem_rr_path[],
chem_rb_path[], chem_prb_path[], chem_mrb_path[],
@@ -66,23 +71,23 @@ path
chem_midt_path[], chem_midb_path[], chem_midst_path[], chem_midsb_path[] ;
chem_setting_scale := 1 ;
-chem_base_width := 40pt ;
-chem_text_offset := 3pt ;
+chem_base_width := 40pt ; % Should this rather follow the font size?
+chem_text_offset := 3pt ; % ?
chem_center_offset := 6pt ;
-chem_picture_offset := 10pt ;
-chem_substituent_offset := 10pt ;
+chem_picture_offset := 10pt ; % Should this follow chem_base_width (thus the font size)?
+chem_substituent_offset := 10pt ; % Should this follow chem_base_width (thus the font size)?
chem_radical_min := 1.25 ;
chem_radical_max := 1.50 ;
chem_text_min := 0.75 ;
-chem_text_max := 1.75 ;
+chem_text_max := 1.25 ;
chem_circle_radius := 0.80 ;
chem_circle_radius := 1.10 ;
-chem_rotation := 1 ;
+chem_rotation := 0 ;
chem_adjacent := 0 ;
chem_substituent := 0 ;
chem_direction := 0 ;
chem_stack_n := 0 ;
-chem_doing_pb := false ;
+chem_doing_pb := false ;
chem_shift := origin ;
chem_dot_factor := 4 ;
chem_text_trace := false ;
@@ -90,8 +95,10 @@ chem_bd_n := 4 ;
chem_bw_n := 4 ;
chem_bd_angle := 4 ;
chem_bb_angle := 4 ;
+chem_axis_color := blue ; % TODO: add "axiscolor=" option in lua...
vardef chem_start_structure(expr n, l, r, t, b, scale, axis, fixedwidth, fixedheight, offset) =
+ % note that "n" is not used...
chem_setting_axis := axis ;
chem_setting_l := l * scale ;
chem_setting_r := r * scale ;
@@ -104,7 +111,7 @@ vardef chem_start_structure(expr n, l, r, t, b, scale, axis, fixedwidth, fixedhe
chem_setting_scale := scale ;
chem_init_all ;
fi ;
- chem_rotation := 1 ;
+ chem_rotation := 0 ;
chem_adjacent := 0 ;
chem_substituent := 0 ;
chem_direction := 0 ;
@@ -127,17 +134,18 @@ def chem_stop_structure =
chem_setting_bbox :=
(-chem_setting_l,-chem_setting_b) -- ( chem_setting_r,-chem_setting_b) --
( chem_setting_r, chem_setting_t) -- (-chem_setting_l, chem_setting_t) -- cycle ;
- % maybe put it behind the picture
- if chem_setting_axis :
+ if chem_setting_axis : % put it behind the picture
+ picture chem_picture ; chem_picture := currentpicture ; currentpicture := nullpicture ;
save stp ; stp := chem_base_width/ 2 * chem_setting_scale ;
- save siz ; siz := chem_base_width/10 * chem_setting_scale ;
- draw (-chem_setting_l,0) -- (chem_setting_r,0) withcolor blue ;
- draw (0,-chem_setting_b) -- (0,chem_setting_t) withcolor blue ;
- for i = 0 step stp until chem_setting_r : draw (i,-siz) -- (i,siz) withcolor blue ; endfor ;
- for i = 0 step -stp until -chem_setting_l : draw (i,-siz) -- (i,siz) withcolor blue ; endfor ;
- for i = 0 step stp until chem_setting_t : draw (-siz,i) -- (siz,i) withcolor blue ; endfor ;
- for i = 0 step -stp until -chem_setting_b : draw (-siz,i) -- (siz,i) withcolor blue ; endfor ;
- draw chem_setting_bbox withcolor blue ;
+ save siz ; siz := stp/5 ;
+ draw (-chem_setting_l,0) -- (chem_setting_r,0) withcolor chem_axis_color ;
+ draw (0,-chem_setting_b) -- (0,chem_setting_t) withcolor chem_axis_color ;
+ for i = 0 step stp until chem_setting_r : draw (i,-siz) -- (i,siz) withcolor chem_axis_color ; endfor ;
+ for i = 0 step -stp until -chem_setting_l : draw (i,-siz) -- (i,siz) withcolor chem_axis_color ; endfor ;
+ for i = 0 step stp until chem_setting_t : draw (-siz,i) -- (siz,i) withcolor chem_axis_color ; endfor ;
+ for i = 0 step -stp until -chem_setting_b : draw (-siz,i) -- (siz,i) withcolor chem_axis_color ; endfor ;
+ % frame=on: draw chem_setting_bbox withcolor chem_axis_color ;
+ addto currentpicture also chem_picture ;
fi ;
setbounds currentpicture to chem_setting_bbox ;
enddef ;
@@ -146,8 +154,8 @@ 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 ;
+% draw boundingbox currentpicture withpen pencircle scaled 1mm withcolor chem_axis_color ;
+% draw origin withpen pencircle scaled 2mm withcolor chem_axis_color ;
chem_doing_pb := true ;
enddef ;
@@ -174,6 +182,7 @@ vardef chem_do (expr p) =
fi
enddef ;
+% f_rom, t_o, r_ule, c_olor
vardef chem_b (expr n, f, t, r, c) =
chem_draw (n, chem_b_path[n], f, t, r, c) ;
enddef ;
@@ -221,13 +230,8 @@ vardef chem_eb (expr 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) ;
- chem_draw (n, chem_psb_path [n], f, t, r, c) ;
- else :
- chem_draw (n, chem_dbl_path [n], f, t, r, c) ;
- chem_draw (n, chem_dbr_path [n], f, t, r, c) ;
- fi ;
+ chem_draw (n, chem_dbl_path [n], f, t, r, c) ;
+ chem_draw (n, chem_dbr_path [n], f, t, r, c) ;
enddef ;
vardef chem_er (expr n, f, t, r, c) =
@@ -313,7 +317,7 @@ vardef chem_psr (expr 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)
+ chem_draw (n, chem_c_path[n], f, f, r, c)
enddef ;
vardef chem_cc (expr n, f, t, r, c) =
@@ -321,7 +325,7 @@ vardef chem_cc (expr n, f, t, r, c) =
enddef ;
vardef chem_cd (expr n, f, t, r, c) =
- chem_dashed_connected (n, chem_c_path[n], f, t, r, c)
+ chem_dashed_connected (n, chem_c_path[n], f, f, r, c)
enddef ;
vardef chem_ccd (expr n, f, t, r, c) =
@@ -341,13 +345,13 @@ vardef chem_rbn (expr 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) ;
+ chem_draw (n, chem_tbl_path [n], f, t, r, c) ;
+ chem_draw (n, chem_sb_path [n], f, t, r, c) ;
+ chem_draw (n, chem_tbr_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) ;
+ chem_draw (n, (subpath (.25,.75) of chem_e_path[n]), f, t, r, c) ;
enddef ;
vardef chem_es (expr n, f, t, r, c) = % one
@@ -355,8 +359,8 @@ vardef chem_es (expr n, f, t, r, c) = % one
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) ;
+ chem_draw_dot (n, point .25 of chem_e_path[n], f, t, r, c) ;
+ chem_draw_dot (n, point .75 of chem_e_path[n], f, t, r, c) ;
enddef ;
vardef chem_et (expr n, f, t, r, c) = % one
@@ -373,11 +377,11 @@ 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) ;
+ chem_draw (n, chem_sb_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_sb_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 ;
@@ -388,10 +392,11 @@ vardef chem_hb (expr n, f, t, r, c) = % one
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
+vardef chem_bb (expr n, f, t, r, c) = % one and front
if n < 0 :
- chem_fill (n, chem_bb_path[n], 1, 1, r, c) ;
- chem_b (n, f, t, r, c) ;
+ if ((f = 1) and (t = -n)) : % ignore all but "BB"
+ chem_fill (n, chem_bb_path[n], 1, 1, r, c) ;
+ fi
else :
chem_fill (n, chem_bb_path[n], f, t, r, c) ;
fi ;
@@ -428,7 +433,9 @@ vardef chem_z@#(expr n, p) (text t) =
enddef ;
vardef chem_cz@#(expr n, p) (text t) =
- if n = 1 :
+ if p = 0 :
+ chem_text@#(t, chem_do(origin)) ;
+ elseif n = 1 :
chem_c_text(t, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ;
else :
chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ;
@@ -439,12 +446,37 @@ vardef chem_midz@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_mid_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+string mfun_auto_align[] ;
+mfun_auto_align[0] := "rt" ;
+mfun_auto_align[1] := "urt" ;
+mfun_auto_align[2] := "top" ;
+mfun_auto_align[3] := "ulft" ;
+mfun_auto_align[4] := "lft" ;
+mfun_auto_align[5] := "llft" ;
+mfun_auto_align[6] := "bot" ;
+mfun_auto_align[7] := "lrt" ;
+mfun_auto_align[8] := "rt" ;
+
+def autoalign(expr n) =
+ scantokens mfun_auto_align[round((n mod 360)/45)]
+enddef ;
+
+% draw textext.autoalign(60) ("\strut oeps 1") ;
+% draw textext.autoalign(160)("\strut oeps 2") ;
+% draw textext.autoalign(260)("\strut oeps 3") ;
+% draw textext.autoalign(360)("\strut oeps 4") ;
+
+
vardef chem_rz@#(expr n, p) (text t) =
if n < 0 :
% quite special
chem_text@#(t, chem_do(chem_r_zero[n] shifted (chem_b_zero[n] rotated chem_ang(n,p)))) ;
else :
- chem_text@#(t, chem_do(chem_r_zero[n] rotated chem_ang(n,p))) ;
+ if (length(str @#)>0) and (str @# = "auto") :
+ chem_text.autoalign(chem_ang(n,p-.5)) (t, chem_do(chem_r_zero[n] rotated chem_ang(n,p))) ;
+ else :
+ chem_text@#(t, chem_do(chem_r_zero[n] rotated chem_ang(n,p))) ;
+ fi
fi ;
enddef ;
@@ -483,35 +515,27 @@ vardef chem_rbt@#(expr n, p) (text t) =
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))) ;
- else :
- chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+ chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
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))) ;
- else :
- chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+ chem_zt@#(n, p, t) ;
enddef ;
vardef chem_zbt@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
+ chem_text@#(t, chem_do(chem_zbt_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))) ;
+ chem_zbt@#(n, p, t) ;
enddef ;
vardef chem_ztt@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
+ chem_text@#(t, chem_do(chem_ztt_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))) ;
+ chem_ztt@#(n, p, t) ;
enddef ;
vardef chem_symbol(expr t) =
@@ -545,11 +569,13 @@ vardef chem_c_text(expr txt, z) = % adapted copy of thelabel@
enddef ;
vardef chem_ang (expr n, d) =
- ((-1 * (d-1) * chem_angle[n]) + (-chem_rotation+1) * 90 + chem_start[n]) % no ;
+ ((1 - d)*chem_angle[n] + if (n<0): -90 else: chem_rotation fi) % no ;
enddef ;
vardef chem_rot (expr n, d) =
- chem_rotation := d ;
+ if (d <> 0) :
+ chem_rotation := chem_rotation + 180/(if (d=1): 8 else: abs(d) fi) ;
+ fi
enddef ;
vardef chem_adj (expr n, d) =
@@ -562,7 +588,7 @@ 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))) ;
+ chem_direction_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d))/cosd(chem_angle[n])) ;
currentpicture := currentpicture shifted chem_direction_p ;
chem_shift := chem_shift + chem_direction_p ;
fi ;
@@ -573,23 +599,21 @@ vardef chem_mov (expr n, d) =
currentpicture := currentpicture shifted - chem_shift ;
chem_shift := origin ;
else :
- chem_move_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d+chem_initialmov[n]))) ;
+ %chem_move_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d+chem_initialmov[n]))) ;
+ chem_move_p := -chem_b_zero[n] rotated chem_ang(n,d+chem_initialmov[n]) ;
currentpicture := currentpicture shifted chem_move_p ;
chem_shift := chem_shift + chem_move_p ;
+ %if (n = 3) or (n = 5) : chem_rot(n, -n) ; fi
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) ;
- chem_shift := chem_shift + (-chem_setting_offset,0)
- elseif (d = 4) or (d = 5) or (d = 6) : % negative
- currentpicture := currentpicture shifted ( chem_setting_offset,0) ;
- chem_shift := chem_shift + ( chem_setting_offset,0)
- fi ;
+ pair o ; o := (-chem_setting_offset,0) rotated chem_ang(1,d+chem_initialmov[1]) ;
+ currentpicture := currentpicture shifted o ;
+ chem_shift := chem_shift + o ;
enddef ;
-vardef chem_set(expr n, m) =
+vardef chem_set (expr n, m) =
if chem_adjacent > 0 :
chem_adjacent_d := xpart chem_b_zero[n] + xpart chem_b_zero[m] ;
if chem_adjacent = 1 : chem_adjacent_p := (-chem_adjacent_d, 0) ;
@@ -618,7 +642,6 @@ vardef chem_set(expr n, m) =
chem_shift := chem_shift + chem_substituent_p ;
chem_substituent := 0 ;
fi ;
- chem_rotation := chem_initialrot[m] ;
enddef ;
vardef chem_draw (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
@@ -678,7 +701,7 @@ vardef chem_save =
chem_shift := origin ;
% chem_adjacent := 0 ;
% chem_substituent := 0 ;
-% chem_rotation := 1 ;
+% chem_rotation := 0 ;
currentpicture := nullpicture ;
enddef ;
@@ -693,14 +716,16 @@ vardef chem_restore =
fi ;
enddef ;
-def chem_init_some(expr n, ratio, start, initialrot, initialmov) =
- chem_width [n] := ratio * chem_base_width * chem_setting_scale ;
+def chem_init_some(expr n) =
+ boolean front ; front := n < 0 ;
chem_angle [n] := 360/abs(n) ;
- chem_start [n] := start ;
- chem_initialrot[n] := initialrot ;
- chem_initialmov[n] := initialmov ;
- chem_b_zero [n] := (chem_width[n],0) rotated (chem_angle[n]/2) ;
- chem_n_zero [n] := (chem_text_min*chem_width[n],0) rotated (chem_angle[n]/2) ;
+ chem_initialmov[n] := 0 ;
+ chem_width [n] := chem_setting_scale * (chem_base_width/2) / sind(chem_angle[n]/2) ;
+ chem_dbl_offset[n] := chem_setting_scale * chem_base_width / 20 ;
+ chem_b_path [n] := ((chem_width[n],0) rotated -(chem_angle[n]/2))--
+ ((chem_width[n],0) rotated +(chem_angle[n]/2)) ;
+ chem_b_zero [n] := point 1 of chem_b_path [n] ;
+ chem_n_zero [n] := chem_text_min*chem_b_zero[n] ;
chem_r_max [n] := chem_radical_max*chem_b_zero[n] ;
chem_r_path [n] := chem_b_zero[n] -- chem_r_max[n] ;
chem_mr_path [n] := chem_r_path [n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
@@ -709,119 +734,120 @@ def chem_init_some(expr n, ratio, start, initialrot, initialmov) =
chem_mr_zero [n] := point 1 of chem_mr_path[n] ;
chem_pr_zero [n] := point 1 of chem_pr_path[n] ;
chem_crz_zero [n] := point 1 of (chem_r_path[n] enlonged chem_center_offset) ;
- chem_au_path [n] := subpath (0.2,0.8) of (chem_r_max[n] -- (chem_r_max[n] rotated chem_angle[n])) ;
+ chem_ztt_zero [n] := chem_text_max*(center chem_b_path[n]) ;
+ chem_zbt_zero [n] := chem_text_min*(center chem_b_path[n]) ;
+ chem_au_path [n] := chem_b_path[n] paralleled ((1-chem_text_max)*(abs(center chem_b_path[n]))) ;
chem_ad_path [n] := reverse(chem_au_path[n]) ;
chem_rt_zero [n] := (((chem_radical_max+chem_radical_min)/2)*chem_width[n],0) rotated (chem_angle[n]/2) ;
chem_rtt_zero [n] := chem_rt_zero[n] rotated + 10 ;
chem_rbt_zero [n] := chem_rt_zero[n] rotated - 10 ;
- chem_b_path [n] := reverse(chem_b_zero[n] -- (chem_b_zero[n] rotated -chem_angle[n])) ;
- chem_bx_path [n] := reverse(chem_b_zero[n] -- (chem_b_zero[n] rotated -chem_angle[n])) ; % ?
+ chem_bx_path [n] := reverse(chem_b_zero[n] -- (chem_b_zero[n] rotated -chem_angle[n])) ; % ? NOT USED...
chem_sb_path [n] := subpath (0.25,0.75) of chem_b_path[n] ;
+ chem_msb_path [n] := subpath (0.00,0.75) of chem_b_path[n] ;
+ chem_psb_path [n] := subpath (0.25,1.00) of chem_b_path[n] ;
+ chem_dbl_path [n] := chem_sb_path[n] paralleled - chem_dbl_offset[n] ;
+ chem_dbr_path [n] := chem_sb_path[n] paralleled + chem_dbl_offset[n] ;
+ chem_eb_path [n] := chem_sb_path[n] paralleled +2chem_dbl_offset[n] ;
+ chem_c_path [n] := (fullcircle scaled 2)
+ scaled (abs(center chem_b_path[n]) - 2chem_dbl_offset[n]) ;
+ chem_cc_path [n] := (subpath (0,(length chem_c_path[n])*(1-1/n)) of chem_c_path[n])
+ rotated chem_angle[n] ;
chem_s_path [n] := point 0 of chem_b_path[n] -- point 0 of (chem_b_path[n] rotated (2chem_angle[n])) ;
chem_ss_path [n] := subpath (0.25,0.75) of (chem_s_path[n]) ;
chem_pss_path [n] := subpath (0.00,0.75) of (chem_s_path[n]) ;
chem_mss_path [n] := subpath (0.25,1.00) of (chem_s_path[n]) ;
chem_mid_zero [n] := origin shifted (-.25chem_width[n],0) ;
- chem_midst_path[n] := chem_mid_zero[n] -- (chem_width[n],0) rotated ( chem_angle[n] + chem_angle[n]/2) ;
- chem_midsb_path[n] := chem_mid_zero[n] -- (chem_width[n],0) rotated (-chem_angle[n] - chem_angle[n]/2) ;
- chem_midt_path [n] := subpath (0.25,1.00) of chem_midst_path [n] ;
- chem_midb_path [n] := subpath (0.25,1.00) of chem_midsb_path [n] ;
- chem_msb_path [n] := subpath (0.00,0.75) of chem_b_path[n] ;
- chem_psb_path [n] := subpath (0.25,1.00) of chem_b_path[n] ;
- chem_dbl_path [n] := chem_sb_path[n] shifted - (0.05[origin,center chem_sb_path[n]]) ; % parallel
- chem_dbr_path [n] := chem_sb_path[n] shifted + (0.05[origin,center chem_sb_path[n]]) ;
- chem_eb_path [n] := chem_sb_path[n] shifted - (0.25[origin,center chem_sb_path[n]]) ;
+ chem_midt_path[n] := chem_mid_zero[n] -- chem_b_zero[n] rotated (+chem_angle[n]*floor(n/4)) ;
+ chem_midb_path[n] := chem_mid_zero[n] -- chem_b_zero[n] rotated (-chem_angle[n]*ceiling(n/4)) ;
+ chem_midst_path [n] := subpath (0.25,1.00) of chem_midt_path [n] ;
+ chem_midsb_path [n] := subpath (0.25,1.00) of chem_midb_path [n] ;
chem_sr_path [n] := chem_radical_min*chem_b_zero[n] -- chem_r_max[n] ;
- chem_rl_path [n] := chem_r_path[n] paralleled (chem_base_width/20) ;
- chem_rr_path [n] := chem_r_path[n] paralleled -(chem_base_width/20) ;
- chem_srl_path [n] := chem_sr_path[n] paralleled (chem_base_width/20) ;
- chem_srr_path [n] := chem_sr_path[n] paralleled -(chem_base_width/20) ;
+ chem_rl_path [n] := chem_r_path[n] paralleled +chem_dbl_offset[n] ;
+ chem_rr_path [n] := chem_r_path[n] paralleled -chem_dbl_offset[n] ;
+ chem_srl_path [n] := chem_sr_path[n] paralleled +chem_dbl_offset[n] ;
+ chem_srr_path [n] := chem_sr_path[n] paralleled -chem_dbl_offset[n] ;
chem_br_path [n] := point 1 of chem_sb_path[n] --
point 0 of chem_sb_path[n] rotatedaround(point 1 of chem_sb_path[n], -4) --
point 0 of chem_sb_path[n] rotatedaround(point 1 of chem_sb_path[n], 4) -- cycle ;
chem_rb_path [n] := chem_b_zero[n] -- chem_r_max[n] rotated -2 -- chem_r_max[n] -- chem_r_max[n] rotated 2 -- cycle ;
- chem_mrb_path [n] := chem_rb_path[n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
+ chem_mrb_path [n] := chem_rb_path[n] rotatedaround(chem_b_zero[n],+(180-chem_angle[n])/2) ;
chem_prb_path [n] := chem_rb_path[n] rotatedaround(chem_b_zero[n],-(180-chem_angle[n])/2) ;
- chem_msr_path [n] := chem_sr_path[n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
+ chem_msr_path [n] := chem_sr_path[n] rotatedaround(chem_b_zero[n],+(180-chem_angle[n])/2) ;
chem_psr_path [n] := chem_sr_path[n] rotatedaround(chem_b_zero[n],-(180-chem_angle[n])/2) ;
- % not yet ok:
-% chem_c_path [n] := subpath (30/45, -30/45) of (fullcircle scaled (1.25*chem_circle_radius*chem_width[n]));
-% chem_cc_path [n] := subpath (30/45,8-30/45) of (fullcircle rotated 90 scaled (1.25*chem_circle_radius*chem_width[n]));
- chem_c_path [n] := subpath (30/45, -30/45) of (fullcircle scaled (chem_width[n]));
- chem_cc_path [n] := subpath (30/45,8-30/45) of (fullcircle rotated 90 scaled (chem_width[n]));
+
+ if (front) :
+ chem_bb_path [n] := chem_b_path[n] rotated -chem_angle[n] --
+ chem_b_path[n] --
+ chem_b_path[n] rotated +chem_angle[n] --
+ (reverse(chem_b_path[n])) % shortened (.5chem_dbl_offset[n])))
+ paralleled chem_dbl_offset[n] --
+ cycle ;
+ chem_mr_path [n] := origin -- origin shifted (0,-.25chem_base_width) ;
+ chem_pr_path [n] := origin -- origin shifted (0,+.25chem_base_width) ;
+ chem_mr_zero [n] := point 1 of chem_mr_path[n] ;
+ chem_pr_zero [n] := point 1 of chem_pr_path[n] ;
+ chem_r_path [n] := chem_mr_zero[n] -- chem_pr_zero[n] ;
+ fi
enddef ;
-def chem_init_three = chem_init_some(3,30/52 ,-60,1,2) ; enddef ; % 60
-def chem_init_four = chem_init_some(4,30/42.5, 0,1,0) ; enddef ; % 45
-def chem_init_five = chem_init_some(5,30/35 , 0,1,0) ; enddef ; % 36
-def chem_init_six = chem_init_some(6, 1 , 0,1,0) ; enddef ; % 30
-def chem_init_eight = chem_init_some(8,30/22.5, 0,1,0) ; enddef ; % 22.5
+def chem_init_three = chem_init_some(3) ; enddef ;
+def chem_init_four = chem_init_some(4) ; enddef ;
+def chem_init_five = chem_init_some(5) ; enddef ;
+def chem_init_six = chem_init_some(6) ; enddef ;
+def chem_init_eight = chem_init_some(8) ; enddef ;
+def chem_init_five_front = chem_init_some(-5) ; enddef ;
+def chem_init_six_front = chem_init_some(-6) ; enddef ;
% bb R -R R Z -RZ +RZ
-def chem_init_some_front(expr n, ratio, start, initialrot, initialmov) =
- chem_init_some(n, ratio, start, initialrot, initialmov) ;
- chem_bb_path [n] := chem_b_path[n] rotated -chem_angle[n] -- chem_b_path[n] -- chem_b_path[n] rotated chem_angle[n] --
- (reverse(chem_b_path[n] shortened (chem_base_width/20))) paralleled (chem_base_width/20) --
- cycle ;
- chem_r_max [n] := chem_radical_max*chem_b_zero[n] ;
- chem_mr_path [n] := origin -- origin shifted (0,-.25chem_base_width) ;
- chem_pr_path [n] := origin -- origin shifted (0, .25*chem_base_width) ;
- chem_r_path [n] := point 1 of chem_mr_path[n] -- point 1 of chem_pr_path[n] ;
- chem_mr_zero [n] := point 1 of chem_mr_path[n] ;
- chem_pr_zero [n] := point 1 of chem_pr_path[n] ;
-enddef ;
-
-def chem_init_five_front = chem_init_some_front(-5,30/35,0,2,0) ; enddef ; % 36
-def chem_init_six_front = chem_init_some_front(-6, 1 ,0,2,0) ; enddef ; % 30
-
vardef chem_init_one =
- chem_width [1] := .75 * chem_base_width * chem_setting_scale ;
chem_angle [1] := 360/8 ;
- chem_start [1] := 0 ;
- chem_initialrot[1] := 1 ;
- chem_initialmov[1] := 1 ;
- chem_b_zero [1] := (1.75*chem_width[1],0) ;
- chem_r_min [1] := chem_radical_min*chem_b_zero[1] ;
+ chem_initialmov[1] := 0 ;
+ chem_width [1] := chem_setting_scale * chem_base_width ;
+ chem_dbl_offset[1] := chem_width[1] / 20 ;
+ chem_b_path [1] := origin -- (chem_width[1],0) ;
+ chem_b_zero [1] := point 1 of chem_b_path[1] ;
chem_r_max [1] := chem_radical_max*chem_b_zero[1] ;
- chem_r_path [1] := (.5*chem_width[1],0) -- (1.25*chem_width[1],0) ;
- chem_r_zero [1] := point 1 of chem_r_path [1] ;
- chem_b_path [1] := chem_r_path[1] rotated + (chem_angle[1]) ; % used for move here
- chem_b_zero [1] := chem_r_zero[1] ;
- chem_crz_zero [1] := chem_r_zero[1] enlonged chem_center_offset ;
- chem_e_path [1] := (.5*chem_width[1],-.25*chem_width[1]) -- (.5*chem_width[1],.25*chem_width[1]) ;
- chem_sb_path [1] := chem_r_path [1] ;
- chem_msb_path [1] := chem_r_path [1] shifted (0,-.1chem_width[1]) ;
- chem_psb_path [1] := chem_r_path [1] shifted (0, .1chem_width[1]) ;
- chem_ddt_path [1] := subpath(0,.4) of chem_r_path [1] ;
- chem_ddb_path [1] := subpath(.6,1) of chem_r_path [1] ;
- chem_ldt_path [1] := chem_ddt_path [1] shifted (0,-.1chem_width[1]) ; % parallel
- chem_ldb_path [1] := chem_ddb_path [1] shifted (0,-.1chem_width[1]) ;
- chem_rdt_path [1] := chem_ddt_path [1] shifted (0, .1chem_width[1]) ;
- chem_rdb_path [1] := chem_ddb_path [1] shifted (0, .1chem_width[1]) ;
+ chem_r_path [1] := (center chem_b_path[1]) -- (chem_radical_min*chem_b_zero[1]) ;
+ chem_r_zero [1] := point 1 of chem_r_path[1] ;
+ chem_crz_zero [1] := chem_r_zero[1] enlonged chem_center_offset ; % ???
+ chem_e_path [1] := ((1,-.5) -- (1,+.5)) scaled (.25chem_width[1]) ;
+ chem_sb_path [1] := subpath (0.25,0.75) of chem_b_path[1] ;
+ chem_msb_path [1] := subpath (0, 0.75) of chem_b_path[1] ;
+ chem_psb_path [1] := subpath (0.25,1) of chem_b_path[1] ;
+ chem_ddt_path [1] := subpath (0, 0.4) of chem_sb_path[1] ;
+ chem_ddb_path [1] := subpath (0.6, 1) of chem_sb_path[1] ;
+ chem_dbl_path [1] := chem_sb_path[1] paralleled -1chem_dbl_offset[1] ;
+ chem_dbr_path [1] := chem_sb_path[1] paralleled +1chem_dbl_offset[1] ;
+ chem_tbl_path [1] := chem_sb_path[1] paralleled -2chem_dbl_offset[1] ;
+ chem_tbr_path [1] := chem_sb_path[1] paralleled +2chem_dbl_offset[1] ;
+ chem_ldt_path [1] := chem_ddt_path[1] paralleled -2chem_dbl_offset[1] ;
+ chem_ldb_path [1] := chem_ddb_path[1] paralleled -2chem_dbl_offset[1] ;
+ chem_rdt_path [1] := chem_ddt_path[1] paralleled +2chem_dbl_offset[1] ;
+ chem_rdb_path [1] := chem_ddb_path[1] paralleled +2chem_dbl_offset[1] ;
+ chem_n_zero [1] := center chem_b_path[1] ;
+ chem_ztt_zero [1] := chem_n_zero[1] rotated +.5chem_angle[1] ;
+ chem_zbt_zero [1] := chem_n_zero[1] rotated -.5chem_angle[1] ;
save pr ; pair pr[] ;
- pr0 := point 0 of chem_r_path[1] ;
- pr1 := point 1 of chem_r_path[1] ;
- chem_bb_path [1] := pr0 -- (pr1 rotatedaround(pr0,-chem_bb_angle)) -- (pr1 rotatedaround(pr0,chem_bb_angle)) -- cycle ;
+ pr0 := point 0 of chem_sb_path[1] ;
+ pr1 := point 1 of chem_sb_path[1] ;
+ chem_bb_path [1] := pr0 -- (pr1 rotatedaround(pr0,-chem_bb_angle)) --
+ (pr1 rotatedaround(pr0,+chem_bb_angle)) -- cycle ;
chem_oe_path [1] := ((-20,0)--(10,0){up}..(20,10)..(30,0)..(40,-10)..(50.0,0)..(60,10)..(70,0)..(80,-10)..{up}(90,0)--(120,0))
- xsized (.75*chem_width[1]) shifted pr0 ;
- chem_rt_zero [1] := point .5 of chem_r_path[1] ;
- chem_rtt_zero [1] := chem_rt_zero[1] rotated + (chem_angle[1]/2) ;
- chem_rbt_zero [1] := chem_rt_zero[1] rotated - (chem_angle[1]/2) ;
- % added by Alan Braslau (adapted to use shared variables):
+ xsized (abs(pr1-pr0)) shifted pr0 ;
save p ; pair p[] ;
p0 := pr1 rotatedaround(pr0, -chem_bd_angle) ;
p1 := pr1 rotatedaround(pr0, +chem_bd_angle) ;
- p2 := p0 shifted - pr1 ;
- p3 := p1 shifted - pr1 ;
+ p2 := p0 shifted -pr1 ;
+ p3 := p1 shifted -pr1 ;
chem_bd_path [1] :=
p0 -- p1 for i=chem_bd_n downto 0 :
- -- p2 shifted (i/chem_bd_n)[pr1,pr0]
- -- p3 shifted (i/chem_bd_n)[pr1,pr0]
+ -- p2 shifted (i/chem_bd_n)[pr1,pr0]
+ -- p3 shifted (i/chem_bd_n)[pr1,pr0]
endfor ;
chem_bw_path [1] :=
for i=0 upto chem_bw_n - 1 :
- ((i) /chem_bw_n)[pr0,pr1] .. ((i+.25)/chem_bw_n)[pr0,pr1] shifted p2 ..
+ ((i) /chem_bw_n)[pr0,pr1] .. ((i+.25)/chem_bw_n)[pr0,pr1] shifted +p2 ..
((i+.50)/chem_bw_n)[pr0,pr1] .. ((i+.75)/chem_bw_n)[pr0,pr1] shifted -p2 ..
endfor pr1 ;
enddef ;
diff --git a/metapost/context/base/mp-core.mpiv b/metapost/context/base/mp-core.mpiv
index 1934e3040..3dba4a004 100644
--- a/metapost/context/base/mp-core.mpiv
+++ b/metapost/context/base/mp-core.mpiv
@@ -5,7 +5,7 @@
%D subtitle=background 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/metapost/context/base/mp-crop.mpiv b/metapost/context/base/mp-crop.mpiv
index 6360757e5..00bcdcb44 100644
--- a/metapost/context/base/mp-crop.mpiv
+++ b/metapost/context/base/mp-crop.mpiv
@@ -5,7 +5,7 @@
%D subtitle=Cropmarks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ 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,20 +15,20 @@ 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 ;
+vardef crop_marks_lines (expr box, len, 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) ;
+ draw ((llcorner box) -- (llcorner box) shifted (-len,0)) shifted (-offset,i*h) ;
+ draw ((lrcorner box) -- (lrcorner box) shifted ( len,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) ;
+ draw ((llcorner box) -- (llcorner box) shifted (0,-len)) shifted (i*w,-offset) ;
+ draw ((ulcorner box) -- (ulcorner box) shifted (0, len)) shifted (i*w, offset) ;
endfor ;
) ;
setbounds p to box ;
diff --git a/metapost/context/base/mp-figs.mpiv b/metapost/context/base/mp-figs.mpiv
index c65808f6d..aac7c5ad2 100644
--- a/metapost/context/base/mp-figs.mpiv
+++ b/metapost/context/base/mp-figs.mpiv
@@ -5,7 +5,7 @@
%D subtitle=figures,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={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/metapost/context/base/mp-form.mpiv b/metapost/context/base/mp-form.mpiv
index d0519b4f2..b58792e1a 100644
--- a/metapost/context/base/mp-form.mpiv
+++ b/metapost/context/base/mp-form.mpiv
@@ -5,7 +5,7 @@
%D subtitle=form 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 licen-en.pdf for
diff --git a/metapost/context/base/mp-func.mpiv b/metapost/context/base/mp-func.mpiv
index 1d289b606..58df711f2 100644
--- a/metapost/context/base/mp-func.mpiv
+++ b/metapost/context/base/mp-func.mpiv
@@ -5,7 +5,7 @@
%D subtitle=function 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 licen-en.pdf for
diff --git a/metapost/context/base/mp-grap.mpiv b/metapost/context/base/mp-grap.mpiv
new file mode 100644
index 000000000..757413a1c
--- /dev/null
+++ b/metapost/context/base/mp-grap.mpiv
@@ -0,0 +1,204 @@
+%D \module
+%D [ file=mp-grap.mpiv,
+%D version=2012.10.16, % 2008.09.08 and earlier,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=graph packagesupport,
+%D author=Hans Hagen \& Alan Braslau,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if known context_grap : endinput ; fi ;
+
+boolean context_grap ; context_grap := true ;
+
+input graph.mp ;
+
+vardef roundd(expr x, d) =
+ if abs d > 4 :
+ if d > 0 :
+ x
+ else :
+ 0
+ fi
+ elseif d > 0 :
+ save i ; i = floor x ;
+ i + round(Ten_to[d]*(x-i))/Ten_to[d]
+ else :
+ round(x/Ten_to[-d])*Ten_to[-d]
+ fi
+enddef ;
+
+Ten_to0 = 1 ;
+Ten_to1 = 10 ;
+Ten_to2 = 100 ;
+Ten_to3 = 1000 ;
+Ten_to4 = 10000 ;
+
+def sFe_base = enddef ;
+
+if unknown Fe_plus :
+ picture Fe_plus ; Fe_plus := textext("+") ; % btex + etex ;
+fi ;
+
+vardef format (expr f,x) = dofmt_.Feform_(f,x) enddef ;
+vardef Mformat (expr f,x) = dofmt_.Meform (f,x) enddef ;
+vardef formatstr (expr f,x) = dofmt_.Feform_(f,x) enddef ;
+vardef Mformatstr(expr f,x) = dofmt_.Meform(f,x) enddef ;
+
+vardef escaped_format(expr s) =
+ "" for n=1 upto length(s) : &
+ if ASCII substring (n,n+1) of s = 37 :
+ "@"
+ else :
+ substring (n,n+1) of s
+ fi
+ endfor
+enddef ;
+
+vardef dofmt_@#(expr f, x) =
+ textext("\MPgraphformat{" & escaped_format(f) & "}{" & (if string x : x else: decimal x fi) & "}")
+ % textext(mfun_format_number(escaped_format(f),x))
+enddef ;
+
+% We redefine autogrid from graph.mp adding the possibility of differing X and Y
+% formats. Autoform is defined in graph.mp (by default "%g").
+%
+% string Autoform_X ; Autoform_X := "@.0e" ;
+% string Autoform_Y ; Autoform_Y := "@.0e" ;
+
+vardef autogrid(suffix tx, ty) text w =
+ Gneedgr_ := false ;
+ if str tx <> "" :
+ for x=auto.x :
+ tx (
+ if string Autoform_X :
+ if Autoform_X <> "" :
+ Autoform_X
+ else :
+ Autoform
+ fi
+ else :
+ Autoform
+ fi,
+ x) w ;
+ endfor
+ fi ;
+ if str ty <> "" :
+ for y=auto.y :
+ ty (
+ if string Autoform_Y :
+ if Autoform_Y <> "" :
+ Autoform_Y
+ else :
+ Autoform
+ fi
+ else :
+ Autoform
+ fi,
+ y) w ;
+ endfor
+ fi ;
+enddef ;
+
+% A couple of extensions:
+
+% Define a vector function sym returning a picture: 10 different shapes,
+% unfilled outline, interior filled with different shades of the background.
+% Thus, overlapping points on a plot are more clearly distinguishable.
+
+% grap_symsize := fontsize defaultfont ; % can be redefined
+%
+% dynamic version:
+
+vardef grap_symsize =
+ % fontsize defaultfont
+ % .8ExHeight
+ .35BodyFontSize
+enddef ;
+
+path grap_sym[] ; % (internal) symbol path
+
+grap_sym[0] := (0,0) ; % point
+grap_sym[1] := fullcircle ; % circle
+grap_sym[2] := (up -- down) scaled .5 ; % vertical bar
+
+for i = 3 upto 9 : % polygons
+ grap_sym[i] := for j = 0 upto i-1 :
+ (up scaled .5) rotated (j*360/i) --
+ endfor cycle ;
+endfor
+
+grap_sym[12] := grap_sym[2] rotated +90 ; % horizontal line
+grap_sym[22] := grap_sym[2] rotated +45 ; % backslash
+grap_sym[32] := grap_sym[2] rotated -45 ; % slash
+grap_sym[13] := grap_sym[3] rotated 180 ; % down triangle
+grap_sym[23] := grap_sym[3] rotated -90 ; % right triangle
+grap_sym[33] := grap_sym[3] rotated +90 ; % left triangle
+grap_sym[14] := grap_sym[4] rotated +45 ; % square
+grap_sym[15] := grap_sym[5] rotated 180 ; % down pentagon
+grap_sym[16] := grap_sym[6] rotated +90 ; % turned hexagon
+grap_sym[17] := grap_sym[7] rotated 180 ;
+grap_sym[18] := grap_sym[8] rotated +22.5 ;
+
+numeric l ;
+
+for j = 5 upto 9 :
+ l := length(grap_sym[j]) ;
+ pair p[] ;
+ for i = 0 upto l :
+ p[i] = whatever [point i of grap_sym[j],
+ point (i+2 mod l) of grap_sym[j]] ;
+ p[i] = whatever [point (i+1 mod l) of grap_sym[j],
+ point (i+l-1 mod l) of grap_sym[j]] ;
+ endfor
+ grap_sym[20+j] := for i = 0 upto l : point i of grap_sym[j]--p[i]--endfor cycle ;
+endfor
+
+path s ; s := grap_sym[4] ;
+path q ; q := s scaled .25 ;
+numeric l ; l := length(s) ;
+
+pair p[] ;
+
+grap_sym[24] := for i = 0 upto l-1 :
+ hide(
+ p[i] = whatever [point i of s, point (i+1 mod l) of s] ;
+ p[i] = whatever [point i of q, point (i-1+l mod l) of q] ;
+ p[i+l] = whatever [point i of s, point (i+1 mod l) of s] ;
+ p[i+l] = whatever [point i+1 of q, point (i+2 mod l) of q] ;
+ )
+ point i of q -- p[i] -- p[i+l] --
+endfor cycle ;
+
+grap_sym[34] := grap_sym[24] rotated 45 ;
+
+ % usage: gdraw p plot plotsymbol(1,red,1) ; % a filled red circle
+ % usage: gdraw p plot plotsymbol(4,blue,0) ; % a blue square
+ % usage: gdraw p plot plotsymbol(14,green,0.5) ; % a 50% filled green diamond
+
+def plotsymbol(expr n,c,f) = % (number,color,color|number)
+ if known grap_sym[n] :
+ image(
+ path p ; p := grap_sym[n] scaled grap_symsize ;
+ undraw p withpen currentpen scaled 2 ;
+ if cycle p : fill p withcolor
+ if color f and known f :
+ f
+ elseif numeric f and known f and color c and known c :
+ f[background,c]
+ elseif numeric f and known f :
+ f[background,black]
+ else :
+ background
+ fi ;
+ fi
+ draw p if color c and known c : withcolor c fi ;
+ )
+ else :
+ nullpicture
+ fi
+enddef ;
diff --git a/metapost/context/base/mp-grid.mpiv b/metapost/context/base/mp-grid.mpiv
index cc5c2b76e..b9243b1b9 100644
--- a/metapost/context/base/mp-grid.mpiv
+++ b/metapost/context/base/mp-grid.mpiv
@@ -5,7 +5,7 @@
%D subtitle=grid 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 licen-en.pdf for
diff --git a/metapost/context/base/mp-grph.mpiv b/metapost/context/base/mp-grph.mpiv
index a8868033b..30c49e6e0 100644
--- a/metapost/context/base/mp-grph.mpiv
+++ b/metapost/context/base/mp-grph.mpiv
@@ -5,7 +5,7 @@
%D subtitle=graphic text 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 licen-en.pdf for
diff --git a/metapost/context/base/mp-mlib.mpiv b/metapost/context/base/mp-mlib.mpiv
index 71985cef8..b8fabbfb9 100644
--- a/metapost/context/base/mp-mlib.mpiv
+++ b/metapost/context/base/mp-mlib.mpiv
@@ -5,7 +5,7 @@
%D subtitle=plugins,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={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
@@ -255,7 +255,7 @@ vardef thetextext@#(expr p,z) =
fi
enddef ;
-vardef textext@#(expr p) = % no draw hers
+vardef textext@#(expr p) = % no draw here
thetextext@#(p,origin)
enddef ;
@@ -614,3 +614,28 @@ primarydef t asgroup s = % s = isolated|knockout
wrappedpicture
endgroup
enddef ;
+
+% Also experimental
+
+string mfun_auto_align[] ;
+
+mfun_auto_align[0] := "rt" ;
+mfun_auto_align[1] := "urt" ;
+mfun_auto_align[2] := "top" ;
+mfun_auto_align[3] := "ulft" ;
+mfun_auto_align[4] := "lft" ;
+mfun_auto_align[5] := "llft" ;
+mfun_auto_align[6] := "bot" ;
+mfun_auto_align[7] := "lrt" ;
+mfun_auto_align[8] := "rt" ;
+
+def autoalign(expr n) =
+ scantokens mfun_auto_align[round((n mod 360)/45)]
+enddef ;
+
+% draw textext.autoalign(60) ("\strut oeps 1") ;
+% draw textext.autoalign(160)("\strut oeps 2") ;
+% draw textext.autoalign(260)("\strut oeps 3") ;
+% draw textext.autoalign(360)("\strut oeps 4") ;
+
+
diff --git a/metapost/context/base/mp-page.mpiv b/metapost/context/base/mp-page.mpiv
index 96f617257..c8e3c6237 100644
--- a/metapost/context/base/mp-page.mpiv
+++ b/metapost/context/base/mp-page.mpiv
@@ -5,7 +5,7 @@
%D subtitle=page enhancements,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
diff --git a/metapost/context/base/mp-shap.mpiv b/metapost/context/base/mp-shap.mpiv
index b62e636d5..713656510 100644
--- a/metapost/context/base/mp-shap.mpiv
+++ b/metapost/context/base/mp-shap.mpiv
@@ -5,7 +5,7 @@
%D subtitle=shapes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={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/metapost/context/base/mp-step.mpiv b/metapost/context/base/mp-step.mpiv
index 654ef443d..f7a7ba5de 100644
--- a/metapost/context/base/mp-step.mpiv
+++ b/metapost/context/base/mp-step.mpiv
@@ -5,7 +5,7 @@
%D subtitle=steps,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={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/metapost/context/base/mp-text.mpiv b/metapost/context/base/mp-text.mpiv
index d5630f68e..b68e8412a 100644
--- a/metapost/context/base/mp-text.mpiv
+++ b/metapost/context/base/mp-text.mpiv
@@ -5,7 +5,7 @@
%D subtitle=text 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 licen-en.pdf for
diff --git a/metapost/context/base/mp-tool.mpiv b/metapost/context/base/mp-tool.mpiv
index 764863b65..cdf0e02a9 100644
--- a/metapost/context/base/mp-tool.mpiv
+++ b/metapost/context/base/mp-tool.mpiv
@@ -5,12 +5,14 @@
%D subtitle=auxiliary 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.
+% def loadfile(expr name) = scantokens("input " & name & ";") enddef ;
+
if known context_tool : endinput ; fi ;
boolean context_tool ; context_tool := true ;
diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua
index e07ecdfc7..f33363a0d 100644
--- a/scripts/context/lua/mtx-context.lua
+++ b/scripts/context/lua/mtx-context.lua
@@ -6,11 +6,18 @@ if not modules then modules = { } end modules ['mtx-context'] = {
license = "see context related readme files"
}
+-- todo: more local functions
+-- todo: pass jobticket/ctxdata table around
+
local format, gmatch, match, gsub, find = string.format, string.gmatch, string.match, string.gsub, string.find
-local quote = string.quote
+local quote, validstring = string.quote, string.valid
local concat = table.concat
+local settings_to_array = utilities.parsers.settings_to_array
+local appendtable = table.append
+local lpegpatterns, lpegmatch, Cs, P = lpeg.patterns, lpeg.match, lpeg.Cs, lpeg.P
-local getargument = environment.argument
+local getargument = environment.getargument or environment.argument
+local setargument = environment.setargument
local basicinfo = [[
--run process (one or more) files (default action)
@@ -35,8 +42,10 @@ local basicinfo = [[
--noconsole disable logging to the console (logfile only)
--purgeresult purge result file before run
---forcexml force xml stub (optional flag: --mkii)
+--forcexml force xml stub
--forcecld force cld (context lua document) stub
+--forcelua force lua stub (like texlua)
+--forcemp force mp stub
--arrange run extra imposition pass, given that the style sets up imposition
--noarrange ignore imposition specifications in the style
@@ -50,23 +59,16 @@ local basicinfo = [[
--version report installed context version
--global assume given file present elsewhere
+--nofile use dummy file as jobname
--expert expert options
]]
--- filter=list is kind of obsolete
--- color is obsolete for mkiv, always on
--- separation is obsolete for mkiv, no longer available
--- output is currently obsolete for mkiv
--- setuppath=list must check
--- modefile=name must check
--- input=name load the given inputfile (must check)
-
local expertinfo = [[
expert options:
--touch update context version number (remake needed afterwards, also provide --expert)
---nostats omit runtime statistics at the end of the run
+--nostatistics omit runtime statistics at the end of the run
--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
@@ -80,13 +82,14 @@ special options:
--pdftex process file with texexec using pdftex
--xetex process file with texexec using xetex
+--mkii process file with texexec
--pipe don't check for file and enter scroll mode (--dummyfile=whatever.tmp)
]]
local application = logs.application {
name = "mtx-context",
- banner = "ConTeXt Process Management 0.52",
+ banner = "ConTeXt Process Management 0.60",
helpinfo = {
basic = basicinfo,
extra = extrainfo,
@@ -94,159 +97,105 @@ local application = logs.application {
}
}
+-- local luatexflags = {
+-- ["8bit"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["default-translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["etex"] = true, -- ignored, the etex extensions are always active
+--
+-- ["credits"] = true, -- display credits and exit
+-- ["debug-format"] = true, -- enable format debugging
+-- ["disable-write18"] = true, -- disable \write18{SHELL COMMAND}
+-- ["draftmode"] = true, -- switch on draft mode (generates no output PDF)
+-- ["enable-write18"] = true, -- enable \write18{SHELL COMMAND}
+-- ["file-line-error"] = true, -- enable file:line:error style messages
+-- ["file-line-error-style"] = true, -- aliases of --file-line-error
+-- ["no-file-line-error"] = true, -- disable file:line:error style messages
+-- ["no-file-line-error-style"] = true, -- aliases of --no-file-line-error
+-- ["fmt"] = true, -- load the format file FORMAT
+-- ["halt-on-error"] = true, -- stop processing at the first error
+-- ["help"] = true, -- display help and exit
+-- ["ini"] = true, -- be iniluatex, for dumping formats
+-- ["interaction"] = true, -- set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode)
+-- ["jobname"] = true, -- set the job name to STRING
+-- ["kpathsea-debug"] = true, -- set path searching debugging flags according to the bits of NUMBER
+-- ["lua"] = true, -- load and execute a lua initialization script
+-- ["mktex"] = true, -- enable mktexFMT generation (FMT=tex/tfm)
+-- ["no-mktex"] = true, -- disable mktexFMT generation (FMT=tex/tfm)
+-- ["nosocket"] = true, -- disable the lua socket library
+-- ["output-comment"] = true, -- use STRING for DVI file comment instead of date (no effect for PDF)
+-- ["output-directory"] = true, -- use existing DIR as the directory to write files in
+-- ["output-format"] = true, -- use FORMAT for job output; FORMAT is 'dvi' or 'pdf'
+-- ["parse-first-line"] = true, -- enable parsing of the first line of the input file
+-- ["no-parse-first-line"] = true, -- disable parsing of the first line of the input file
+-- ["progname"] = true, -- set the program name to STRING
+-- ["recorder"] = true, -- enable filename recorder
+-- ["safer"] = true, -- disable easily exploitable lua commands
+-- ["shell-escape"] = true, -- enable \write18{SHELL COMMAND}
+-- ["no-shell-escape"] = true, -- disable \write18{SHELL COMMAND}
+-- ["shell-restricted"] = true, -- restrict \write18 to a list of commands given in texmf.cnf
+-- ["synctex"] = true, -- enable synctex
+-- ["version"] = true, -- display version and exit
+-- ["luaonly"] = true, -- run a lua file, then exit
+-- ["luaconly"] = true, -- byte-compile a lua file, then exit
+-- }
+
local report = application.report
scripts = scripts or { }
scripts.context = scripts.context or { }
--- a demo cld file:
---
--- context.starttext()
--- context.chapter("Hello There")
--- context.readfile("tufte","","not found")
--- context.stoptext()
-
--- l-file / todo
+-- constants
-function file.needsupdate(oldfile,newfile)
- return true
-end
-function file.syncmtimes(oldfile,newfile)
-end
+local usedfiles = {
+ nop = "cont-nop.mkiv",
+ yes = "cont-yes.mkiv",
+}
--- l-io
+local usedsuffixes = {
+ before = {
+ "tuc"
+ },
+ after = {
+ "pdf", "tuc", "log"
+ },
+ keep = {
+ "log"
+ },
+}
-function io.copydata(fromfile,tofile)
- io.savedata(tofile,io.loaddata(fromfile) or "")
-end
+local formatofinterface = {
+ en = "cont-en",
+ uk = "cont-uk",
+ de = "cont-de",
+ fr = "cont-fr",
+ nl = "cont-nl",
+ cs = "cont-cs",
+ it = "cont-it",
+ ro = "cont-ro",
+ pe = "cont-pe",
+}
--- ctx (will become util-ctx)
-
-local ctxrunner = { }
-
-function ctxrunner.filtered(str,method)
- str = tostring(str)
- if method == 'name' then str = file.removesuffix(file.basename(str))
- elseif method == 'path' then str = file.dirname(str)
- elseif method == 'suffix' then str = file.extname(str)
- elseif method == 'nosuffix' then str = file.removesuffix(str)
- elseif method == 'nopath' then str = file.basename(str)
- elseif method == 'base' then str = file.basename(str)
--- elseif method == 'full' then
--- elseif method == 'complete' then
--- elseif method == 'expand' then -- str = file.expandpath(str)
- end
- return str:gsub("\\","/")
-end
+local defaultformats = {
+ "cont-en",
+ "cont-nl",
+}
-function ctxrunner.substitute(e,str)
- local attributes = e.at
- if str and attributes then
- if attributes['method'] then
- str = ctxrunner.filtered(str,attributes['method'])
- end
- if str == "" and attributes['default'] then
- str = attributes['default']
- end
- end
- return str
-end
+-- process information
-function ctxrunner.reflag(flags)
- local t = { }
- for _, flag in next, flags do
- local key, value = match(flag,"^(.-)=(.+)$")
- if key and value then
- t[key] = value
- else
- t[flag] = true
- end
- end
- return t
-end
+local ctxrunner = { } -- namespace will go
-function ctxrunner.substitute(str)
- return str
-end
-
-function ctxrunner.justtext(str)
- str = xml.unescaped(tostring(str))
- str = xml.cleansed(str)
- str = str:gsub("\\+",'/')
- str = str:gsub("%s+",' ')
- return str
-end
+local ctx_locations = { '..', '../..' }
function ctxrunner.new()
return {
- ctxname = "",
- jobname = "",
- xmldata = nil,
- suffix = "prep",
- locations = { '..', '../..' },
- variables = { },
- messages = { },
- environments = { },
- modules = { },
- filters = { },
- flags = { },
- modes = { },
- prepfiles = { },
- paths = { },
+ ctxname = "",
+ jobname = "",
+ flags = { },
}
end
-function ctxrunner.savelog(ctxdata,ctlname)
- local function yn(b)
- if b then return 'yes' else return 'no' end
- end
- if not ctlname or ctlname == "" or ctlname == ctxdata.jobname then
- if ctxdata.jobname then
- ctlname = file.replacesuffix(ctxdata.jobname,'ctl')
- elseif ctxdata.ctxname then
- ctlname = file.replacesuffix(ctxdata.ctxname,'ctl')
- else
- report("invalid ctl name: %s",ctlname or "?")
- return
- end
- end
- local prepfiles = ctxdata.prepfiles
- if prepfiles and next(prepfiles) then
- report("saving logdata in: %s",ctlname)
- f = io.open(ctlname,'w')
- if f then
- f:write("<?xml version='1.0' standalone='yes'?>\n\n")
- f:write(format("<ctx:preplist local='%s'>\n",yn(ctxdata.runlocal)))
- local sorted = table.sortedkeys(prepfiles)
- for i=1,#sorted do
- local name = sorted[i]
- f:write(format("\t<ctx:prepfile done='%s'>%s</ctx:prepfile>\n",yn(prepfiles[name]),name))
- end
- f:write("</ctx:preplist>\n")
- f:close()
- end
- else
- report("nothing prepared, no ctl file saved")
- os.remove(ctlname)
- end
-end
-
-function ctxrunner.register_path(ctxdata,path)
- -- test if exists
- ctxdata.paths[ctxdata.paths+1] = path
-end
-
-function ctxrunner.trace(ctxdata)
- print(table.serialize(ctxdata.messages))
- print(table.serialize(ctxdata.flags))
- print(table.serialize(ctxdata.environments))
- print(table.serialize(ctxdata.modules))
- print(table.serialize(ctxdata.filters))
- print(table.serialize(ctxdata.modes))
- print(xml.tostring(ctxdata.xmldata))
-end
-
-function ctxrunner.manipulate(ctxdata,ctxname,defaultname)
+function ctxrunner.checkfile(ctxdata,ctxname,defaultname)
if not ctxdata.jobname or ctxdata.jobname == "" then
return
@@ -269,13 +218,14 @@ function ctxrunner.manipulate(ctxdata,ctxname,defaultname)
local usedname = ctxdata.ctxname
local found = lfs.isfile(usedname)
- -- no futher test if qualified path
+ -- no further test if qualified path
if not found then
- for _, path in next, ctxdata.locations do
+ for _, path in next, ctx_locations do
local fullname = file.join(path,ctxdata.ctxname)
if lfs.isfile(fullname) then
- usedname, found = fullname, true
+ usedname = fullname
+ found = true
break
end
end
@@ -283,194 +233,70 @@ function ctxrunner.manipulate(ctxdata,ctxname,defaultname)
if not found then
usedname = resolvers.findfile(ctxdata.ctxname,"tex")
- found = usedname ~= ""
+ found = usedname ~= ""
end
if not found and defaultname and defaultname ~= "" and lfs.isfile(defaultname) then
- usedname, found = defaultname, true
+ usedname = defaultname
+ found = true
end
if not found then
return
end
- ctxdata.xmldata = xml.load(usedname)
+ local xmldata = xml.load(usedname)
- if not ctxdata.xmldata then
+ if not xmldata then
return
else
-- test for valid, can be text file
end
- xml.include(ctxdata.xmldata,'ctx:include','name', table.append({'.', file.dirname(ctxdata.ctxname)},ctxdata.locations))
-
- ctxdata.variables['job'] = ctxdata.jobname
-
- ctxdata.flags = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:flags/ctx:flag",true)
- ctxdata.environments = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:environment",true)
- ctxdata.modules = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:module",true)
- ctxdata.filters = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:filter",true)
- ctxdata.modes = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:mode",true)
- ctxdata.messages = xml.collect_texts(ctxdata.xmldata,"ctx:message",true)
-
- ctxdata.flags = ctxrunner.reflag(ctxdata.flags)
-
- local messages = ctxdata.messages
- for i=1,#messages do
- report("ctx comment: %s", xml.tostring(messages[i]))
- end
-
- for r, d, k in xml.elements(ctxdata.xmldata,"ctx:value[@name='job']") do
- d[k] = ctxdata.variables['job'] or ""
- end
-
- local commands = { }
- for e in xml.collected(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do
- commands[e.at and e.at['name'] or "unknown"] = e
- end
-
- local suffix = xml.filter(ctxdata.xmldata,"/ctx:job/ctx:preprocess/attribute('suffix')") or ctxdata.suffix
- local runlocal = xml.filter(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:processors/attribute('local')")
-
- runlocal = toboolean(runlocal)
-
- for files in xml.collected(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:files") do
- for pattern in xml.collected(files,"ctx:file") do
+ local ctxpaths = table.append({'.', file.dirname(ctxdata.ctxname)}, ctx_locations)
- preprocessor = pattern.at['processor'] or ""
+ xml.include(xmldata,'ctx:include','name', ctxpaths)
- if preprocessor ~= "" then
+ local flags = ctxdata.flags
- ctxdata.variables['old'] = ctxdata.jobname
- for r, d, k in xml.elements(ctxdata.xmldata,"ctx:value") do
- local ek = d[k]
- local ekat = ek.at['name']
- if ekat == 'old' then
- d[k] = ctxrunner.substitute(ctxdata.variables[ekat] or "")
- end
- end
-
- pattern = ctxrunner.justtext(xml.tostring(pattern))
-
- local oldfiles = dir.glob(pattern)
-
- local pluspath = false
- if #oldfiles == 0 then
- -- message: no files match pattern
- local paths = ctxdata.paths
- for i=1,#paths do
- local p = paths[i]
- local oldfiles = dir.glob(path.join(p,pattern))
- if #oldfiles > 0 then
- pluspath = true
- break
- end
- end
- end
- if #oldfiles == 0 then
- -- message: no old files
- else
- for i=1,#oldfiles do
- local oldfile = oldfiles[i]
- local newfile = oldfile .. "." .. suffix -- addsuffix will add one only
- if ctxdata.runlocal then
- newfile = file.basename(newfile)
- end
- if oldfile ~= newfile and file.needsupdate(oldfile,newfile) then
- -- message: oldfile needs preprocessing
- -- os.remove(newfile)
- local splitted = preprocessor:split(',')
- for i=1,#splitted do
- local pp = splitted[i]
- local command = commands[pp]
- if command then
- command = xml.copy(command)
- local suf = (command.at and command.at['suffix']) or ctxdata.suffix
- if suf then
- newfile = oldfile .. "." .. suf
- end
- if ctxdata.runlocal then
- newfile = file.basename(newfile)
- end
- for r, d, k in xml.elements(command,"ctx:old") do
- d[k] = ctxrunner.substitute(oldfile)
- end
- for r, d, k in xml.elements(command,"ctx:new") do
- d[k] = ctxrunner.substitute(newfile)
- end
- ctxdata.variables['old'] = oldfile
- ctxdata.variables['new'] = newfile
- for r, d, k in xml.elements(command,"ctx:value") do
- local ek = d[k]
- local ekat = ek.at and ek.at['name']
- if ekat then
- d[k] = ctxrunner.substitute(ctxdata.variables[ekat] or "")
- end
- end
- -- potential optimization: when mtxrun run internal
- command = xml.content(command)
- command = ctxrunner.justtext(command)
- report("command: %s",command)
- local result = os.spawn(command) or 0
- -- somehow we get the wrong return value
- if result > 0 then
- report("error, return code: %s",result)
- end
- if ctxdata.runlocal then
- oldfile = file.basename(oldfile)
- end
- end
- end
- if lfs.isfile(newfile) then
- file.syncmtimes(oldfile,newfile)
- ctxdata.prepfiles[oldfile] = true
- else
- report("error, check target location of new file: %s", newfile)
- ctxdata.prepfiles[oldfile] = false
- end
- else
- report("old file needs no preprocessing")
- ctxdata.prepfiles[oldfile] = lfs.isfile(newfile)
- end
- end
- end
- end
+ for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do
+ local flag = xml.text(e) or ""
+ local key, value = match(flag,"^(.-)=(.+)$")
+ if key and value then
+ flags[key] = value
+ else
+ flags[flag] = true
end
end
- ctxrunner.savelog(ctxdata)
-
end
-function ctxrunner.preppedfile(ctxdata,filename)
- if ctxdata.prepfiles[file.basename(filename)] then
- return filename .. ".prep"
- else
- return filename
+function ctxrunner.checkflags(ctxdata)
+ if ctxdata then
+ for k,v in next, ctxdata.flags do
+ if getargument(k) == nil then
+ setargument(k,v)
+ end
+ end
end
end
--- rest
+-- multipass control
-scripts.context.multipass = {
--- suffixes = { ".tuo", ".tuc" },
- suffixes = { ".tuc" },
- nofruns = 8,
--- nofruns = 7, -- test oscillation
-}
+local multipass_suffixes = { ".tuc" }
+local multipass_nofruns = 8 -- or 7 to test oscillation
-function scripts.context.multipass.hashfiles(jobname)
+local function multipass_hashfiles(jobname)
local hash = { }
- local suffixes = scripts.context.multipass.suffixes
- for i=1,#suffixes do
- local suffix = suffixes[i]
+ for i=1,#multipass_suffixes do
+ local suffix = multipass_suffixes[i]
local full = jobname .. suffix
hash[full] = md5.hex(io.loaddata(full) or "unknown")
end
return hash
end
-function scripts.context.multipass.changed(oldhash, newhash)
+local function multipass_changed(oldhash, newhash)
for k,v in next, oldhash do
if v ~= newhash[k] then
return true
@@ -479,126 +305,7 @@ function scripts.context.multipass.changed(oldhash, newhash)
return false
end
-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")
- if f then
- local function someflag(flag)
- return (ctxdata and ctxdata.flags[flag]) or getargument(flag)
- end
- local function setvalue(flag,template,hash,default)
- local a = someflag(flag) or default
- if a and a ~= "" then
- if hash then
- if hash[a] then
- f:write(format(template,a),"\n")
- end
- else
- f:write(format(template,a),"\n")
- end
- end
- end
- local function setvalues(flag,template,plural)
- if type(flag) == "table" then
- for k, v in next, flag do
- f:write(format(template,v),"\n")
- end
- else
- local a = someflag(flag) or (plural and someflag(flag.."s"))
- if a and a ~= "" then
- for v in gmatch(a,"%s*([^,]+)") do
- f:write(format(template,v),"\n")
- end
- end
- end
- end
- local function setfixed(flag,template,...)
- if someflag(flag) then
- f:write(format(template,...),"\n")
- end
- end
- local function setalways(template,...)
- f:write(format(template,...),"\n")
- end
- --
- -- This might change ... we can just pass the relevant flags directly.
- --
- setalways("%% runtime options files (command line driven)")
- --
- setalways("\\unprotect")
- --
- setalways("%% feedback and basic job control")
- --
- -- 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 ("nostats" , "\\nomkivstatistics")
- setfixed ("paranoid" , "\\def\\maxreadlevel{1}")
- --
- setalways("%% handy for special styles")
- --
- setalways("\\startluacode")
- setalways("document = document or { }")
- setalways(table.serialize(environment.arguments, "document.arguments"))
- setalways(table.serialize(environment.files, "document.files"))
- setalways("\\stopluacode")
- --
- setalways("%% process info")
- --
- setalways( "\\setupsystem[inputfile=%s]",getargument("input") or environment.files[1] or "\\jobname")
- setvalue ("result" , "\\setupsystem[file=%s]")
- setalways( "\\setupsystem[\\c!n=%s,\\c!m=%s]", kindofrun or 0, currentrun or 0)
- setvalues("path" , "\\usepath[%s]")
- 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)
- if ctxdata then
- setvalues(ctxdata.modes, "\\enablemode[%s]")
- end
- --
- setalways("%% options (not that important)")
- --
- setalways("\\startsetups *runtime:options")
- setfixed ("color" , "\\setupcolors[\\c!state=\\v!start]")
- setvalue ("separation" , "\\setupcolors[\\c!split=%s]")
- setfixed ("noarrange" , "\\setuparranging[\\v!disable]")
- if getargument('arrange') and not finalrun then
- setalways( "\\setuparranging[\\v!disable]")
- end
- setalways("\\stopsetups")
- --
- setalways("%% styles and modules")
- --
- setalways("\\startsetups *runtime:modules")
- setvalues("usemodule" , "\\usemodule[%s]", true)
- setvalues("environment" , "\\environment %s ", true)
- if ctxdata then
- setvalues(ctxdata.modules, "\\usemodule[%s]")
- setvalues(ctxdata.environments, "\\environment %s ")
- end
- setalways("\\stopsetups")
- --
- setalways("%% done")
- --
- setalways("\\protect \\endinput")
- f:close()
- end
-end
-
-function scripts.context.multipass.copyluafile(jobname) -- obsolete
+local function multipass_copyluafile(jobname)
local tuaname, tucname = jobname..".tua", jobname..".tuc"
if lfs.isfile(tuaname) then
os.remove(tucname)
@@ -606,120 +313,54 @@ function scripts.context.multipass.copyluafile(jobname) -- obsolete
end
end
-scripts.context.cldsuffixes = table.tohash {
- "cld",
-}
-
-scripts.context.xmlsuffixes = table.tohash {
- "xml",
-}
-
-scripts.context.luasuffixes = table.tohash {
- "lua",
-}
-
-scripts.context.beforesuffixes = {
- "tuo", "tuc"
-}
-scripts.context.aftersuffixes = {
- "pdf", "tuo", "tuc", "log"
-}
-
-scripts.context.errorsuffixes = {
- "log"
-}
-
-scripts.context.interfaces = {
- en = "cont-en",
- uk = "cont-uk",
- de = "cont-de",
- fr = "cont-fr",
- nl = "cont-nl",
- cs = "cont-cs",
- it = "cont-it",
- ro = "cont-ro",
- pe = "cont-pe",
-}
-
-scripts.context.defaultformats = {
- "cont-en",
- "cont-nl",
--- "mptopdf", -- todo: mak emkiv variant
--- "metatex", -- will show up soon
--- "metafun", -- todo: mp formats
--- "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 = lpeg.match(pattern,line)
+local function preamble_analyze(filename) -- only files on current path
+ local t = { }
+ local line = io.loadlines(file.addsuffix(filename,"tex"))
+ if line then
+ local preamble = lpegmatch(pattern,line)
if preamble then
for key, value in gmatch(preamble,"(%S+)%s*=%s*(%S+)") do
t[key] = value
end
t.type = "tex"
- elseif line:find("^<?xml ") then
+ elseif find(line,"^<?xml ") then
t.type = "xml"
end
if t.nofruns then
- scripts.context.multipass.nofruns = t.nofruns
+ multipass_nofruns = t.nofruns
end
if not t.engine then
t.engine = 'luatex'
end
- f:close()
- return t
- end
-end
-
-local function makestub(wrap,template,filename,prepname)
- local stubname = file.replacesuffix(file.basename(filename),'run')
- local f = io.open(stubname,'w')
- if f then
- if wrap then
- f:write("\\starttext\n")
- end
- f:write(format(template,prepname or filename),"\n")
- if wrap then
- f:write("\\stoptext\n")
- end
- f:close()
- filename = stubname
end
- return filename
+ return t
end
---~ function scripts.context.openpdf(name)
---~ os.spawn(format('pdfopen --file "%s" 2>&1', file.replacesuffix(name,"pdf")))
---~ end
---~ function scripts.context.closepdf(name)
---~ os.spawn(format('pdfclose --file "%s" 2>&1', file.replacesuffix(name,"pdf")))
---~ end
+-- automatically opening and closing pdf files
-local pdfview -- delayed loading
+local pdfview -- delayed
-function scripts.context.openpdf(name,method)
+local function pdf_open(name,method)
pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
pdfview.setmethod(method)
report(pdfview.status())
pdfview.open(file.replacesuffix(name,"pdf"))
end
-function scripts.context.closepdf(name,method)
+local function pdf_close(name,method)
pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
pdfview.setmethod(method)
pdfview.close(file.replacesuffix(name,"pdf"))
end
-local function push_result_purge(oldbase,newbase)
- for _, suffix in next, scripts.context.aftersuffixes do
+-- result file handling
+
+local function result_push_purge(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname)
@@ -727,8 +368,8 @@ local function push_result_purge(oldbase,newbase)
end
end
-local function push_result_keep(oldbase,newbase)
- for _, suffix in next, scripts.context.beforesuffixes do
+local function result_push_keep(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.before do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
local tmpname = "keep-"..oldname
@@ -739,8 +380,8 @@ local function push_result_keep(oldbase,newbase)
end
end
-local function save_result_error(oldbase,newbase)
- for _, suffix in next, scripts.context.errorsuffixes do
+local function result_save_error(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.keep do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname) -- to be sure
@@ -748,8 +389,8 @@ local function save_result_error(oldbase,newbase)
end
end
-local function save_result_purge(oldbase,newbase)
- for _, suffix in next, scripts.context.aftersuffixes do
+local function result_save_purge(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname) -- to be sure
@@ -757,8 +398,8 @@ local function save_result_purge(oldbase,newbase)
end
end
-local function save_result_keep(oldbase,newbase)
- for _, suffix in next, scripts.context.aftersuffixes do
+local function result_save_keep(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
local tmpname = "keep-"..oldname
@@ -768,313 +409,339 @@ local function save_result_keep(oldbase,newbase)
end
end
-function scripts.context.run(ctxdata,filename)
- -- filename overloads environment.files
- local files = (filename and { filename }) or environment.files
- if ctxdata then
- -- todo: interface
- for k,v in next, ctxdata.flags do
- environment.setargument(k,v)
+-- executing luatex
+
+local function flags_to_string(flags,prefix) -- context flags get prepended by c:
+ local t = { }
+ for k, v in table.sortedhash(flags) do
+ if prefix then
+ k = format("c:%s",k)
+ end
+ if not v or v == "" or v == '""' then
+ -- no need to flag false
+ elseif v == true then
+ t[#t+1] = format('--%s',k)
+ elseif type(v) == "string" then
+ t[#t+1] = format('--%s=%s',k,quote(v))
+ else
+ t[#t+1] = format('--%s=%s',k,tostring(v))
end
end
- if #files > 0 then
+ return concat(t," ")
+end
+
+local function luatex_command(l_flags,c_flags,filename)
+ return format('luatex %s %s "%s"',
+ flags_to_string(l_flags),
+ flags_to_string(c_flags,true),
+ filename
+ )
+end
+
+local function run_texexec(filename,a_purge,a_purgeall)
+ if false then
+ -- we need to write a top etc too and run mp etc so it's not worth the
+ -- trouble, so it will take a while before the next is finished
--
- local interface = getargument("interface")
- -- todo: getargument("interface","en")
- interface = (type(interface) == "string" and interface) or "en"
+ -- context --extra=texutil --convert myfile
+ else
+ local texexec = resolvers.findfile("texexec.rb") or ""
+ if texexec ~= "" then
+ os.setenv("RUBYOPT","")
+ local options = environment.reconstructcommandline(environment.arguments_after)
+ options = gsub(options,"--purge","")
+ options = gsub(options,"--purgeall","")
+ local command = format("ruby %s %s",texexec,options)
+ if a_purge then
+ os.execute(command)
+ scripts.context.purge_job(filename,false,true)
+ elseif a_purgeall then
+ os.execute(command)
+ scripts.context.purge_job(filename,true,true)
+ else
+ os.exec(command)
+ end
+ end
+ end
+end
+
+--
+
+function scripts.context.run(ctxdata,filename)
+ --
+ local a_nofile = getargument("nofile")
+ --
+ local files = environment.files or { }
+ --
+ local filelist, mainfile
+ --
+ if filename then
+ -- the given forced name is processed, the filelist is passed to context
+ mainfile = filename
+ filelist = { filename }
+ -- files = files
+ elseif a_nofile then
+ -- the list of given files is processed using the dummy file
+ mainfile = usedfiles.nop
+ filelist = { usedfiles.nop }
+ -- files = { }
+ elseif #files > 0 then
+ -- the list of given files is processed using the stub file
+ mainfile = usedfiles.yes
+ filelist = files
+ files = { }
+ else
+ return
+ end
+ --
+ local interface = validstring(getargument("interface")) or "en"
+ local formatname = formatofinterface[interface] or "cont-en"
+ local formatfile, scriptfile = resolvers.locateformat(formatname)
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (commandline driven)")
+ scripts.context.make(formatname)
+ formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ if formatfile and scriptfile then
+ -- okay
+ elseif formatname then
+ report("error, no format found with name: %s, aborting",formatname)
+ return
+ else
+ report("error, no format found (provide formatname or interface)")
+ return
+ end
+ --
+ local a_mkii = getargument("mkii") or getargument("pdftex") or getargument("xetex")
+ local a_purge = getargument("purge")
+ local a_purgeall = getargument("purgeall")
+ local a_purgeresult = getargument("purgeresult")
+ local a_global = getargument("global")
+ local a_timing = getargument("timing")
+ local a_batchmode = getargument("batchmode")
+ local a_nonstopmode = getargument("nonstopmode")
+ local a_once = getargument("once")
+ local a_synctex = getargument("synctex")
+ local a_backend = getargument("backend")
+ local a_arrange = getargument("arrange")
+ local a_noarrange = getargument("noarrange")
+ --
+ for i=1,#filelist do
--
- local formatname = scripts.context.interfaces[interface] or "cont-en"
- local formatfile, scriptfile = resolvers.locateformat(formatname)
- -- this catches the command line
- if not formatfile or not scriptfile then
- report("warning: no format found, forcing remake (commandline driven)")
- scripts.context.make(formatname)
- formatfile, scriptfile = resolvers.locateformat(formatname)
+ local filename = filelist[i]
+ local basename = file.basename(filename)
+ local pathname = file.dirname(filename)
+ local jobname = file.removesuffix(basename)
+ local ctxname = ctxdata and ctxdata.ctxname
+ --
+ if pathname == "" and not a_global and filename ~= usedfiles.nop then
+ filename = "./" .. filename
end
--
- if formatfile and scriptfile then
- for i=1,#files do
- local filename = files[i]
- local basename, pathname = file.basename(filename), file.dirname(filename)
- local jobname = file.removesuffix(basename)
- if pathname == "" and not getargument("global") then
- filename = "./" .. filename
+ local analysis = preamble_analyze(filename)
+ --
+ if a_mkii or analysis.engine == 'pdftex' or analysis.engine == 'xetex' then
+ run_texexec(filename,a_purge,a_purgeall)
+ else
+ if analysis.interface and analysis.interface ~= interface then
+ formatname = formatofinterface[analysis.interface] or formatname
+ formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (source driven)")
+ scripts.context.make(formatname)
+ formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ if formatfile and scriptfile then
+ --
+ local suffix = validstring(getargument("suffix"))
+ local resultname = validstring(getargument("result"))
+ if suffix then
+ resultname = file.removesuffix(jobname) .. suffix
end
- -- look at the first line
- local a = analyze(filename)
- if a and (a.engine == 'pdftex' or a.engine == 'xetex' or getargument("pdftex") or getargument("xetex")) then
- if false then
- -- we need to write a top etc too and run mp etc so it's not worth the
- -- trouble, so it will take a while before the next is finished
- --
- -- context --extra=texutil --convert myfile
- else
- local texexec = resolvers.findfile("texexec.rb") or ""
- if texexec ~= "" then
- os.setenv("RUBYOPT","")
- local options = environment.reconstructcommandline(environment.arguments_after)
- options = gsub(options,"--purge","")
- options = gsub(options,"--purgeall","")
- local command = format("ruby %s %s",texexec,options)
- if getargument("purge") then
- os.execute(command)
- scripts.context.purge_job(filename,false,true)
- elseif getargument("purgeall") then
- os.execute(command)
- scripts.context.purge_job(filename,true,true)
- else
- os.exec(command)
- end
+ local oldbase = ""
+ local newbase = ""
+ if resultname then
+ oldbase = file.removesuffix(jobname)
+ newbase = file.removesuffix(resultname)
+ if oldbase ~= newbase then
+ if a_purgeresult then
+ result_push_purge(oldbase,newbase)
+ else
+ result_push_keep(oldbase,newbase)
end
+ else
+ resultname = nil
end
- else
- if a and a.interface and a.interface ~= interface then
- formatname = scripts.context.interfaces[a.interface] or formatname
- formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ --
+ local pdfview = getargument("autopdf") or getargument("closepdf")
+ if pdfview then
+ pdf_close(filename,pdfview)
+ if resultname then
+ pdf_close(resultname,pdfview)
end
- -- this catches the command line
- if not formatfile or not scriptfile then
- report("warning: no format found, forcing remake (source driven)")
- scripts.context.make(formatname)
- formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ --
+ local okay = statistics.checkfmtstatus(formatfile)
+ if okay ~= true then
+ report("warning: %s, forcing remake",tostring(okay))
+ scripts.context.make(formatname)
+ end
+ --
+ local oldhash = multipass_hashfiles(jobname)
+ local newhash = { }
+ local maxnofruns = once and 1 or multipass_nofruns
+ --
+ local c_flags = {
+ directives = validstring(environment.directives), -- gets passed via mtxrun
+ trackers = validstring(environment.trackers), -- gets passed via mtxrun
+ experiments = validstring(environment.experiments), -- gets passed via mtxrun
+ --
+ result = validstring(resultname),
+ input = validstring(getargument("input") or filename), -- alternative input
+ fulljobname = validstring(filename),
+ files = concat(files,","),
+ ctx = validstring(ctxname),
+ }
+ --
+ for k, v in next, environment.arguments do
+ if c_flags[k] == nil then
+ c_flags[k] = v
end
- if formatfile and scriptfile then
- -- we default to mkiv xml !
- -- the --prep argument might become automatic (and noprep)
- local suffix = file.extname(filename) or "?"
- if scripts.context.xmlsuffixes[suffix] or getargument("forcexml") then
- if getargument("mkii") then
- filename = makestub(true,"\\processXMLfilegrouped{%s}",filename)
- else
- filename = makestub(true,"\\xmlprocess{\\xmldocument}{%s}{}",filename)
- end
- elseif scripts.context.cldsuffixes[suffix] or getargument("forcecld") then
- -- self contained cld files need to have a starttext/stoptext (less fontloading)
- filename = makestub(false,"\\ctxlua{context.runfile('%s')}",filename)
- elseif scripts.context.luasuffixes[suffix] or getargument("forcelua") then
- filename = makestub(true,"\\ctxlua{dofile('%s')}",filename)
- elseif getargument("prep") then
- -- we need to keep the original jobname
- filename = makestub(true,"\\readfile{%s}{}{}",filename,ctxrunner.preppedfile(ctxdata,filename))
- end
- --
- -- todo: also other stubs
- --
- local suffix, resultname = getargument("suffix"), getargument("result")
- if type(suffix) == "string" then
- resultname = file.removesuffix(jobname) .. suffix
- end
- local oldbase, newbase = "", ""
- if type(resultname) == "string" then
- oldbase = file.removesuffix(jobname)
- newbase = file.removesuffix(resultname)
- if oldbase ~= newbase then
- if getargument("purgeresult") then
- push_result_purge(oldbase,newbase)
- else
- push_result_keep(oldbase,newbase)
- end
- else
- resultname = nil
- end
- else
- resultname = nil
- end
- --
- local pdfview = getargument("autopdf") or getargument("closepdf")
- if pdfview then
- scripts.context.closepdf(filename,pdfview)
- if resultname then
- scripts.context.closepdf(resultname,pdfview)
- end
- end
- --
- local okay = statistics.checkfmtstatus(formatfile)
- if okay ~= true then
- report("warning: %s, forcing remake",tostring(okay))
- scripts.context.make(formatname)
- end
- --
- local flags = { }
- if getargument("batchmode") or getargument("batch") then
- flags[#flags+1] = "--interaction=batchmode"
- end
- if getargument("synctex") then
- -- this should become a directive
- report("warning: synctex is enabled") -- can add upto 5% runtime
- flags[#flags+1] = "--synctex=1"
- end
- flags[#flags+1] = "--fmt=" .. quote(formatfile)
- flags[#flags+1] = "--lua=" .. quote(scriptfile)
- --
- -- We pass these directly.
- --
-
---~ local silent = getargument("silent")
---~ local noconsole = getargument("noconsole")
---~ local directives = getargument("directives")
---~ local trackers = getargument("trackers")
---~ if silent == true then
---~ silent = "*"
---~ end
---~ if type(silent) == "string" then
---~ if type(directives) == "string" then
---~ directives = format("%s,logs.blocked={%s}",directives,silent)
---~ else
---~ directives = format("logs.blocked={%s}",silent)
---~ end
---~ end
---~ if noconsole then
---~ if type(directives) == "string" then
---~ directives = format("%s,logs.target=file",directives)
---~ else
---~ directives = format("logs.target=file")
---~ end
---~ end
-
- local directives = environment.directives
- local trackers = environment.trackers
- local experiments = environment.experiments
-
- --
- if type(directives) == "string" then
- flags[#flags+1] = format('--directives="%s"',directives)
- end
- if type(trackers) == "string" then
- flags[#flags+1] = format('--trackers="%s"',trackers)
- end
- --
- local backend = getargument("backend")
- if type(backend) ~= "string" then
- backend = "pdf"
- end
- flags[#flags+1] = format('--backend="%s"',backend)
- --
- local command = format("luatex %s %s \\stoptext", concat(flags," "), quote(filename))
- local oldhash, newhash = scripts.context.multipass.hashfiles(jobname), { }
- local once = getargument("once")
- local maxnofruns = (once and 1) or scripts.context.multipass.nofruns
- local arrange = getargument("arrange")
- 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,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
- local returncode, errorstring = os.spawn(command)
- --~ if returncode == 3 then
- --~ scripts.context.make(formatname)
- --~ returncode, errorstring = os.spawn(command)
- --~ if returncode == 3 then
- --~ report("ks: return code 3, message: %s",errorstring or "?")
- --~ os.exit(1)
- --~ end
- --~ end
- if not returncode then
- report("fatal error: no return code, message: %s",errorstring or "?")
- if resultname then
- save_result_error(oldbase,newbase)
- end
- os.exit(1)
- break
- elseif returncode > 0 then
- report("fatal error: return code: %s",returncode or "?")
- if resultname then
- save_result_error(oldbase,newbase)
- end
- os.exit(returncode)
- break
- else
- scripts.context.multipass.copyluafile(jobname)
- -- scripts.context.multipass.copytuifile(jobname)
- newhash = scripts.context.multipass.hashfiles(jobname)
- if scripts.context.multipass.changed(oldhash,newhash) then
- oldhash = newhash
- else
- break
- end
- end
- end
- --
- if arrange then
- local kindofrun = 3
- scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,i,true) -- kindofrun, currentrun, final
- report("arrange run: %s",command)
- local returncode, errorstring = os.spawn(command)
- if not returncode then
- report("fatal error: no return code, message: %s",errorstring or "?")
- os.exit(1)
- elseif returncode > 0 then
- report("fatal error: return code: %s",returncode or "?")
- os.exit(returncode)
- end
- end
- --
- if getargument("purge") then
- scripts.context.purge_job(jobname)
- elseif getargument("purgeall") then
- scripts.context.purge_job(jobname,true)
- end
- --
- os.remove(jobname..".top")
- --
+ end
+ --
+ local l_flags = {
+ ["interaction"] = (a_batchmode and "batchmode") or (a_nonstopmode and "nonstopmode") or nil,
+ ["synctex"] = a_synctex and 1 or nil,
+ ["no-parse-first-line"] = true,
+ -- ["no-mktex"] = true,
+ -- ["file-line-error-style"] = true,
+ ["fmt"] = formatfile,
+ ["lua"] = scriptfile,
+ ["jobname"] = jobname,
+ }
+ --
+ if a_synctex then
+ report("warning: synctex is enabled") -- can add upto 5% runtime
+ end
+ --
+ -- kindofrun: 1:first run, 2:successive run, 3:once, 4:last of maxruns
+ --
+ for currentrun=1,maxnofruns do
+ --
+ c_flags.final = false
+ c_flags.kindofrun = (a_once and 3) or (currentrun==1 and 1) or (currentrun==maxnofruns and 4) or 2
+ c_flags.currentrun = currentrun
+ c_flags.noarrange = a_noarrange or a_arrange or nil
+ --
+ local command = luatex_command(l_flags,c_flags,mainfile)
+ --
+ report("run %s: %s",i,command)
+ print("") -- cleaner, else continuation on same line
+ local returncode, errorstring = os.spawn(command)
+ if not returncode then
+ report("fatal error: no return code, message: %s",errorstring or "?")
if resultname then
- if getargument("purgeresult") then
- -- so, if there is no result then we don't get the old one, but
- -- related files (log etc) are still there for tracing purposes
- save_result_purge(oldbase,newbase)
- else
- save_result_keep(oldbase,newbase)
- end
- report("result renamed to: %s",newbase)
- end
- --
- if getargument("purge") then
- scripts.context.purge_job(resultname)
- elseif getargument("purgeall") then
- scripts.context.purge_job(resultname,true)
- end
- --
- local pdfview = getargument("autopdf")
- if pdfview then
- scripts.context.openpdf(resultname or filename,pdfview)
+ result_save_error(oldbase,newbase)
end
- --
- if getargument("timing") then
- report()
- report("you can process (timing) statistics with:",jobname)
- report()
- report("context --extra=timing '%s'",jobname)
- report("mtxrun --script timing --xhtml [--launch --remove] '%s'",jobname)
- report()
+ os.exit(1)
+ break
+ elseif returncode == 0 then
+ multipass_copyluafile(jobname)
+ newhash = multipass_hashfiles(jobname)
+ if multipass_changed(oldhash,newhash) then
+ oldhash = newhash
+ else
+ break
end
else
- if formatname then
- report("error, no format found with name: %s, skipping",formatname)
- else
- report("error, no format found (provide formatname or interface)")
+ report("fatal error: return code: %s",returncode or "?")
+ if resultname then
+ result_save_error(oldbase,newbase)
end
+ os.exit(1) -- (returncode)
break
end
+ --
+ end
+ --
+ if a_arrange then
+ --
+ c_flags.final = true
+ c_flags.kindofrun = 3
+ c_flags.currentrun = c_flags.currentrun + 1
+ c_flags.noarrange = nil
+ --
+ local command = luatex_command(l_flags,c_flags,mainfile)
+ --
+ report("arrange run: %s",command)
+ local returncode, errorstring = os.spawn(command)
+ if not returncode then
+ report("fatal error: no return code, message: %s",errorstring or "?")
+ os.exit(1)
+ elseif returncode > 0 then
+ report("fatal error: return code: %s",returncode or "?")
+ os.exit(returncode)
+ end
+ --
+ end
+ --
+ if a_purge then
+ scripts.context.purge_job(jobname)
+ elseif a_purgeall then
+ scripts.context.purge_job(jobname,true)
+ end
+ --
+ if resultname then
+ if a_purgeresult then
+ -- so, if there is no result then we don't get the old one, but
+ -- related files (log etc) are still there for tracing purposes
+ result_save_purge(oldbase,newbase)
+ else
+ result_save_keep(oldbase,newbase)
+ end
+ report("result renamed to: %s",newbase)
+ end
+ --
+ if purge then
+ scripts.context.purge_job(resultname)
+ elseif purgeall then
+ scripts.context.purge_job(resultname,true)
+ end
+ --
+ local pdfview = getargument("autopdf")
+ if pdfview then
+ pdf_open(resultname or jobname,pdfview)
+ end
+ --
+ if a_timing then
+ report()
+ report("you can process (timing) statistics with:",jobname)
+ report()
+ report("context --extra=timing '%s'",jobname)
+ report("mtxrun --script timing --xhtml [--launch --remove] '%s'",jobname)
+ report()
end
- end
- else
- if formatname then
- report("error, no format found with name: %s, aborting",formatname)
else
- report("error, no format found (provide formatname or interface)")
+ if formatname then
+ report("error, no format found with name: %s, skipping",formatname)
+ else
+ report("error, no format found (provide formatname or interface)")
+ end
+ break
end
end
end
+ --
end
-function scripts.context.pipe()
+function scripts.context.pipe() -- still used?
-- context --pipe
-- context --pipe --purge --dummyfile=whatever.tmp
local interface = getargument("interface")
interface = (type(interface) == "string" and interface) or "en"
- local formatname = scripts.context.interfaces[interface] or "cont-en"
+ local formatname = formatofinterface[interface] or "cont-en"
local formatfile, scriptfile = resolvers.locateformat(formatname)
if not formatfile or not scriptfile then
report("warning: no format found, forcing remake (commandline driven)")
@@ -1087,11 +754,16 @@ function scripts.context.pipe()
report("warning: %s, forcing remake",tostring(okay))
scripts.context.make(formatname)
end
- local flags = {
- "--interaction=scrollmode",
- "--fmt=" .. quote(formatfile),
- "--lua=" .. quote(scriptfile),
- "--backend=pdf",
+ local l_flags = {
+ interaction = "scrollmode",
+ fmt = formatfile,
+ lua = scriptfile,
+ }
+ local c_flags = {
+ backend = "pdf",
+ final = false,
+ kindofrun = 3,
+ currentrun = 1,
}
local filename = getargument("dummyfile") or ""
if filename == "" then
@@ -1100,10 +772,9 @@ function scripts.context.pipe()
else
filename = file.addsuffix(filename,"tmp")
io.savedata(filename,"\\relax")
- scripts.context.multipass.makeoptionfile(filename,{ flags = flags },3,1,false) -- kindofrun, currentrun, final
report("entering scrollmode using '%s' with optionfile, end job with \\end",filename)
end
- local command = format("luatex %s %s", concat(flags," "), quote(filename))
+ local command = luatex_command(l_flags,c_flags,filename)
os.spawn(command)
if getargument("purge") then
scripts.context.purge_job(filename)
@@ -1123,11 +794,9 @@ end
local make_mkiv_format = environment.make_format
local function make_mkii_format(name,engine)
- if getargument(engine) then
- local command = format("mtxrun texexec.rb --make --%s %s",name,engine)
- report("running command: %s",command)
- os.spawn(command)
- end
+ local command = format("mtxrun texexec.rb --make --%s %s",name,engine)
+ report("running command: %s",command)
+ os.spawn(command)
end
function scripts.context.generate()
@@ -1140,14 +809,17 @@ function scripts.context.make(name)
if not getargument("fast") then -- as in texexec
scripts.context.generate()
end
- local list = (name and { name }) or (environment.files[1] and environment.files) or scripts.context.defaultformats
+ local list = (name and { name }) or (environment.files[1] and environment.files) or defaultformats
+ local engine = getargument("engine") or "luatex"
for i=1,#list do
local name = list[i]
- name = scripts.context.interfaces[name] or name or ""
- if name ~= "" then
+ name = formatofinterface[name] or name or ""
+ if name == "" then
+ -- nothing
+ elseif engine == "luatex" then
make_mkiv_format(name)
- make_mkii_format(name,"pdftex")
- make_mkii_format(name,"xetex")
+ elseif engine == "pdftex" or engine == "xetex" then
+ make_mkii_format(name,engine)
end
end
end
@@ -1155,68 +827,77 @@ end
function scripts.context.ctx()
local ctxdata = ctxrunner.new()
ctxdata.jobname = environment.files[1]
- ctxrunner.manipulate(ctxdata,getargument("ctx"))
+ ctxrunner.checkfile(ctxdata,getargument("ctx"))
+ ctxrunner.checkflags(ctxdata)
scripts.context.run(ctxdata)
end
function scripts.context.autoctx()
local ctxdata = nil
- local files = (filename and { filename }) or environment.files
+ local files = environment.files
local firstfile = #files > 0 and files[1]
- if firstfile and file.extname(firstfile) == "xml" then
- local f = io.open(firstfile)
- if f then
- local chunk = f:read(512) or ""
- f:close()
- local ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>")
- if ctxname then
- ctxdata = ctxrunner.new()
- ctxdata.jobname = firstfile
- ctxrunner.manipulate(ctxdata,ctxname)
+ if firstfile then
+ local suffix = file.suffix(firstfile)
+ if suffix == "xml" then
+ local chunk = io.loadchunk(firstfile) -- 1024
+ if chunk then
+ local ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>")
+ if ctxname then
+ ctxdata = ctxrunner.new()
+ ctxdata.jobname = firstfile
+ ctxrunner.checkfile(ctxdata,ctxname)
+ ctxrunner.checkflags(ctxdata)
+ end
end
+ elseif suffix == "tex" then
+ -- maybe but we scan the preamble later too
end
end
scripts.context.run(ctxdata)
end
-local template = [[
-\starttext
- \directMPgraphic{%s}{input "%s"}
-\stoptext
-]]
-
-local loaded = false
+-- no longer ok as mlib-run misses something:
-function scripts.context.metapost()
- local filename = environment.files[1] or ""
- if not loaded then
- dofile(resolvers.findfile("mlib-run.lua"))
- loaded = true
- commands = commands or { }
- commands.writestatus = report -- no longer needed
- end
- local formatname = getargument("format") or "metafun"
- if formatname == "" or type(formatname) == "boolean" then
- formatname = "metafun"
- end
- if getargument("pdf") then
- local basename = file.removesuffix(filename)
- local resultname = getargument("result") or basename
- local jobname = "mtx-context-metapost"
- local tempname = file.addsuffix(jobname,"tex")
- io.savedata(tempname,format(template,"metafun",filename))
- environment.files[1] = tempname
- environment.setargument("result",resultname)
- environment.setargument("once",true)
- scripts.context.run()
- scripts.context.purge_job(jobname,true)
- scripts.context.purge_job(resultname,true)
- elseif getargument("svg") then
- metapost.directrun(formatname,filename,"svg")
- else
- metapost.directrun(formatname,filename,"mps")
- end
-end
+-- local template = [[
+-- \starttext
+-- \directMPgraphic{%s}{input "%s"}
+-- \stoptext
+-- ]]
+--
+-- local loaded = false
+--
+-- function scripts.context.metapost()
+-- local filename = environment.files[1] or ""
+-- if not loaded then
+-- dofile(resolvers.findfile("mlib-run.lua"))
+-- loaded = true
+-- commands = commands or { }
+-- commands.writestatus = report -- no longer needed
+-- end
+-- local formatname = getargument("format") or "metafun"
+-- if formatname == "" or type(formatname) == "boolean" then
+-- formatname = "metafun"
+-- end
+-- if getargument("pdf") then
+-- local basename = file.removesuffix(filename)
+-- local resultname = getargument("result") or basename
+-- local jobname = "mtx-context-metapost"
+-- local tempname = file.addsuffix(jobname,"tex")
+-- io.savedata(tempname,format(template,"metafun",filename))
+-- environment.files[1] = tempname
+-- setargument("result",resultname)
+-- setargument("once",true)
+-- scripts.context.run()
+-- scripts.context.purge_job(jobname,true)
+-- scripts.context.purge_job(resultname,true)
+-- elseif getargument("svg") then
+-- metapost.directrun(formatname,filename,"svg")
+-- else
+-- metapost.directrun(formatname,filename,"mps")
+-- end
+-- end
+
+-- --
function scripts.context.version()
local name = resolvers.findfile("context.mkiv")
@@ -1238,6 +919,8 @@ function scripts.context.version()
end
end
+-- purging files
+
local generic_files = {
"texexec.tex", "texexec.tui", "texexec.tuo",
"texexec.tuc", "texexec.tua",
@@ -1262,7 +945,6 @@ local persistent_runfiles = {
}
local special_runfiles = {
---~ "-mpgraph*", "-mprun*", "-temp-*" -- hm, wasn't this escaped?
"-mpgraph", "-mprun", "-temp-"
}
@@ -1278,9 +960,6 @@ local function purge_file(dfile,cfile)
end
end
-local function remove_special_files(pattern)
-end
-
function scripts.context.purge_job(jobname,all,mkiitoo)
if jobname and jobname ~= "" then
jobname = file.basename(jobname)
@@ -1318,7 +997,7 @@ function scripts.context.purge(all,pattern,mkiitoo)
local deleted = { }
for i=1,#files do
local name = files[i]
- local suffix = file.extname(name)
+ local suffix = file.suffix(name)
local basename = file.basename(name)
if obsolete[suffix] or temporary[suffix] or persistent[suffix] or generic[basename] then
deleted[#deleted+1] = purge_file(name)
@@ -1335,12 +1014,14 @@ function scripts.context.purge(all,pattern,mkiitoo)
end
end
+-- touching files (signals regeneration of formats)
+
local function touch(name,pattern)
local name = resolvers.findfile(name)
local olddata = io.loaddata(name)
if olddata then
local oldversion, newversion = "", os.date("%Y.%m.%d %H:%M")
- local newdata, ok = olddata:gsub(pattern,function(pre,mid,post)
+ local newdata, ok = gsub(olddata,pattern,function(pre,mid,post)
oldversion = mid
return pre .. newversion .. post
end)
@@ -1374,25 +1055,29 @@ function scripts.context.touch()
touchfiles("mkii")
touchfiles("mkiv")
touchfiles("mkvi")
+ touchfiles("mkix")
+ touchfiles("mkxi")
+ else
+ report("touching needs --expert")
end
end
-- modules
local labels = { "title", "comment", "status" }
-local cards = { "*.mkvi", "*.mkiv", "*.tex" }
+local cards = { "*.mkvi", "*.mkiv", "*.mkxi", "*.mkix", "*.tex" }
function scripts.context.modules(pattern)
local list = { }
local found = resolvers.findfile("context.mkiv")
if not pattern or pattern == "" then
-- official files in the tree
- for _, card in ipairs(cards) do
- resolvers.findwildcardfiles(card,list)
+ for i=1,#cards do
+ resolvers.findwildcardfiles(cards[i],list)
end
-- my dev path
- for _, card in ipairs(cards) do
- dir.glob(file.join(file.dirname(found),card),list)
+ for i=1,#cards do
+ dir.glob(file.join(file.dirname(found),cards[i]),list)
end
else
resolvers.findwildcardfiles(pattern,list)
@@ -1405,7 +1090,7 @@ function scripts.context.modules(pattern)
if not done[base] then
done[base] = true
local suffix = file.suffix(base)
- if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" then
+ if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" or suffix == "mkix" or suffix == "mkxi" then
local prefix = match(base,"^([xmst])%-")
if prefix then
v = resolvers.findfile(base) -- so that files on my dev path are seen
@@ -1462,30 +1147,28 @@ end
function scripts.context.extra()
local extra = getargument("extra")
- if type(extra) == "string" then
- if getargument("help") then
- scripts.context.extras(extra)
+ if type(extra) ~= "string" then
+ scripts.context.extras()
+ elseif getargument("help") then
+ scripts.context.extras(extra)
+ else
+ local fullextra = extra
+ if not find(fullextra,"mtx%-context%-") then
+ fullextra = "mtx-context-" .. extra
+ end
+ local foundextra = resolvers.findfile(fullextra)
+ if foundextra == "" then
+ scripts.context.extras()
+ return
else
- local fullextra = extra
- if not find(fullextra,"mtx%-context%-") then
- fullextra = "mtx-context-" .. extra
- end
- local foundextra = resolvers.findfile(fullextra)
- if foundextra == "" then
- scripts.context.extras()
- return
- else
- report("processing extra: %s", foundextra)
- end
- environment.setargument("purgeall",true)
- local result = environment.setargument("result") or ""
- if result == "" then
- environment.setargument("result","context-extra")
- end
- scripts.context.run(nil,foundextra)
+ report("processing extra: %s", foundextra)
end
- else
- scripts.context.extras()
+ setargument("purgeall",true)
+ local result = getargument("result") or ""
+ if result == "" then
+ setargument("result","context-extra")
+ end
+ scripts.context.run(nil,foundextra)
end
end
@@ -1493,25 +1176,27 @@ end
function scripts.context.trackers()
environment.files = { resolvers.findfile("m-trackers.mkiv") }
- scripts.context.multipass.nofruns = 1
- environment.setargument("purgeall",true)
+ multipass_nofruns = 1
+ setargument("purgeall",true)
scripts.context.run()
end
function scripts.context.directives()
environment.files = { resolvers.findfile("m-directives.mkiv") }
- scripts.context.multipass.nofruns = 1
- environment.setargument("purgeall",true)
+ multipass_nofruns = 1
+ setargument("purgeall",true)
scripts.context.run()
end
function scripts.context.logcategories()
environment.files = { resolvers.findfile("m-logcategories.mkiv") }
- scripts.context.multipass.nofruns = 1
- environment.setargument("purgeall",true)
+ multipass_nofruns = 1
+ setargument("purgeall",true)
scripts.context.run()
end
+-- updating (often one will use mtx-update instead)
+
function scripts.context.timed(action)
statistics.timed(action)
end
@@ -1548,7 +1233,7 @@ function scripts.context.update()
local function is_okay(basetree)
for _, tree in next, validtrees do
local pattern = gsub(tree,"%-","%%-")
- if basetree:find(pattern) then
+ if find(basetree,pattern) then
return tree
end
end
@@ -1614,7 +1299,7 @@ function scripts.context.update()
end
for k in zipfile:files() do
local filename = k.filename
- if filename:find("/$") then
+ if find(filename,"/$") then
lfs.mkdir(filename)
else
local data = zip.loaddata(zipfile,filename)
@@ -1652,6 +1337,23 @@ function scripts.context.update()
end
end
+-- getting it done
+
+if getargument("nostats") then
+ setargument("nostatistics",true)
+ setargument("nostat",nil)
+end
+
+if getargument("batch") then
+ setargument("batchmode",true)
+ setargument("batch",nil)
+end
+
+if getargument("nonstop") then
+ setargument("nonstopmode",true)
+ setargument("nonstop",nil)
+end
+
do
local silent = getargument("silent")
@@ -1664,9 +1366,9 @@ do
end
if getargument("once") then
- scripts.context.multipass.nofruns = 1
+ multipass_nofruns = 1
elseif getargument("runs") then
- scripts.context.multipass.nofruns = tonumber(getargument("runs")) or nil
+ multipass_nofruns = tonumber(getargument("runs")) or nil
end
if getargument("profile") then
@@ -1674,7 +1376,6 @@ if getargument("profile") then
end
if getargument("run") then
--- scripts.context.timed(scripts.context.run)
scripts.context.timed(scripts.context.autoctx)
elseif getargument("make") then
scripts.context.timed(function() scripts.context.make() end)
@@ -1682,8 +1383,8 @@ elseif getargument("generate") then
scripts.context.timed(function() scripts.context.generate() end)
elseif getargument("ctx") then
scripts.context.timed(scripts.context.ctx)
-elseif getargument("mp") or getargument("metapost") then
- scripts.context.timed(scripts.context.metapost)
+-- elseif getargument("mp") or getargument("metapost") then
+-- scripts.context.timed(scripts.context.metapost)
elseif getargument("version") then
application.identify()
scripts.context.version()
@@ -1711,10 +1412,7 @@ elseif getargument("showdirectives") or getargument("directives") == true then
scripts.context.directives()
elseif getargument("showlogcategories") then
scripts.context.logcategories()
-elseif getargument("track") and type(getargument("track")) == "boolean" then -- for old times sake, will go
- scripts.context.trackers()
-elseif environment.files[1] then
--- scripts.context.timed(scripts.context.run)
+elseif environment.files[1] or getargument("nofile") then
scripts.context.timed(scripts.context.autoctx)
elseif getargument("pipe") then
scripts.context.timed(scripts.context.pipe)
diff --git a/scripts/context/lua/mtx-convert.lua b/scripts/context/lua/mtx-convert.lua
index b4e6e010b..04ff38aad 100644
--- a/scripts/context/lua/mtx-convert.lua
+++ b/scripts/context/lua/mtx-convert.lua
@@ -83,7 +83,7 @@ function converters.convertpath(inputpath,outputpath)
inputpath = inputpath or "."
outputpath = outputpath or "."
for name in lfs.dir(inputpath) do
- local suffix = file.extname(name)
+ local suffix = file.suffix(name)
if find(name,"%.$") then
-- skip . and ..
elseif converters[suffix] then
@@ -102,7 +102,7 @@ function converters.convertpath(inputpath,outputpath)
end
function converters.convertfile(oldname)
- local suffix = file.extname(oldname)
+ local suffix = file.suffix(oldname)
if converters[suffix] then
local newname = file.replacesuffix(oldname,"pdf")
if oldname == newname then
diff --git a/scripts/context/lua/mtx-epub.lua b/scripts/context/lua/mtx-epub.lua
index 7d1c15774..28a37fec2 100644
--- a/scripts/context/lua/mtx-epub.lua
+++ b/scripts/context/lua/mtx-epub.lua
@@ -11,8 +11,8 @@ if not modules then modules = { } end modules ['mtx-epub'] = {
-- really an id but has some special property). Then there is this ncx suffix
-- thing. Somehow it give the impression of a reversed engineered application
-- format so it will probably take a few cycles to let it become a real
--- clean standard. Thanks to Adam Reviczky for helping to figure out all these
--- puzzling details.
+-- clean standard. Thanks to Adam Reviczky, Luigi Scarso and Andy Thomas for
+-- helping to figure out all the puzzling details.
-- This is preliminary code. At some point we will deal with images as well but
-- first we need a decent strategy to export them. More information will be
@@ -31,7 +31,7 @@ mtxrun --script epub --make mydocument
local application = logs.application {
name = "mtx-epub",
- banner = "ConTeXt EPUB Helpers 0.11",
+ banner = "ConTeXt EPUB Helpers 0.12",
helpinfo = helpinfo,
}
@@ -43,26 +43,27 @@ scripts.epub = scripts.epub or { }
local mimetype = "application/epub+zip"
local container = [[
-<?xml version="1.0" encoding="UTF-8" ?>
+<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
- <rootfile full-path="OPS/%s" media-type="application/oebps-package+xml"/>
+ <rootfile full-path="OEBPS/%s" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
]]
local package = [[
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<package version="2.0" xmlns="http://www.idpf.org/2007/opf" unique-identifier="%s">
<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" >urn:uuid:%s</dc:identifier>
- <dc:creator opf:file-as="Self, My" opf:role="aut">MySelf</dc:creator>
+ <dc:title>%s</dc:title>
+ <dc:language>%s</dc:language>
+ <dc:identifier id="%s" opf:scheme="UUID">urn:uuid:%s</dc:identifier>
+ <dc:creator>%s</dc:creator>
<dc:date>%s</dc:date>
+ <meta name="cover" content="%s" />
</metadata>
<manifest>
@@ -70,13 +71,14 @@ local package = [[
</manifest>
<spine toc="ncx">
+ <itemref idref="cover-xhtml" />
<itemref idref="%s" />
</spine>
</package>
]]
-local item = [[ <item id='%s' href='%s' media-type='%s'/>]]
+local item = [[ <item id="%s" href="%s" media-type="%s"/>]]
local toc = [[
<?xml version="1.0"?>
@@ -108,6 +110,23 @@ local toc = [[
</ncx>
]]
+local coverxhtml = [[
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>cover.xhtml</title>
+ </head>
+ <body>
+ <div>
+ <img src="%s" alt="The cover image" style="max-width: 100%%;" />
+ </div>
+ </body>
+</html>
+]]
+
-- 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
@@ -117,7 +136,7 @@ local toc = [[
local function dumbid(filename)
-- return (string.gsub(os.uuid(),"%-%","")) -- to be tested
- return file.nameonly(filename) .. "-" .. file.extname(filename)
+ return file.nameonly(filename) .. "-" .. file.suffix(filename)
end
local mimetypes = {
@@ -128,6 +147,7 @@ local mimetypes = {
png = "image/png",
jpg = "image/jpeg",
ncx = "application/x-dtbncx+xml",
+ gif = "image/gif",
-- default = "text/plain",
}
@@ -194,9 +214,21 @@ function scripts.epub.make()
local files = specification.files or { file.addsuffix(filename,"xhtml") }
local images = specification.images or { }
local root = specification.root or files[1]
+ local language = specification.language or "en"
+ local creator = specification.author or "My Self"
+ local title = specification.title or "My Title"
+ local firstpage = specification.firstpage or ""
+ local lastpage = specification.lastpage or ""
-- identifier = gsub(identifier,"[^a-zA-z0-9]","")
+ if firstpage ~= "" then
+ images[firstpage] = firstpage
+ end
+ if lastpage ~= "" then
+ images[lastpage] = lastpage
+ end
+
identifier = "BookId" -- weird requirement
local epubname = name
@@ -204,11 +236,12 @@ function scripts.epub.make()
local epubfile = file.replacesuffix(name,"epub")
local epubroot = file.replacesuffix(name,"opf")
local epubtoc = "toc.ncx"
+ local epubcover = "cover.xhtml"
application.report("creating paths in tree %s",epubpath)
lfs.mkdir(epubpath)
lfs.mkdir(file.join(epubpath,"META-INF"))
- lfs.mkdir(file.join(epubpath,"OPS"))
+ lfs.mkdir(file.join(epubpath,"OEBPS"))
local used = { }
@@ -217,13 +250,14 @@ function scripts.epub.make()
local mime = mimetypes[suffix]
if mime then
local idmaker = idmakers[suffix] or idmakers.default
- local target = file.join(epubpath,"OPS",filename)
+ local target = file.join(epubpath,"OEBPS",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("cover.xhtml")
copyone("toc.ncx")
local function copythem(files)
@@ -241,7 +275,7 @@ function scripts.epub.make()
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
+ if not lfs.isfile(k) and file.suffix(k) == "svg" and file.suffix(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)
@@ -250,33 +284,52 @@ function scripts.epub.make()
copythem(theimages)
- local idmaker = idmakers[file.extname(root)] or idmakers.default
-
- container = format(container,epubroot)
- 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)
+ local idmaker = idmakers[file.suffix(root)] or idmakers.default
+
+ container = format(container,
+ epubroot
+ )
+ package = format(package,
+ identifier,
+ title,
+ language,
+ identifier,
+ os.uuid(),
+ creator,
+ os.date("!%Y-%m-%dT%H:%M:%SZ"),
+ idmaker(firstpage),
+ concat(used,"\n"),
+ idmaker(root)
+ )
+ toc = format(toc,
+ identifier,
+ title,
+ root
+ )
+ coverxhtml = format(coverxhtml,
+ firstpage
+ )
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)
+ io.savedata(file.join(epubpath,"OEBPS",epubroot),package)
+ io.savedata(file.join(epubpath,"OEBPS",epubtoc),toc)
+ io.savedata(file.join(epubpath,"OEBPS",epubcover),coverxhtml)
application.report("creating archive\n\n")
- local done = false
- local list = { }
-
lfs.chdir(epubpath)
os.remove(epubfile)
+ local done = false
+
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"))
+ os.execute(format(zipper.compressed,epubfile,"OEBPS"))
done = zipper.name
- else
- list[#list+1] = zipper.name
+ break
end
end
@@ -285,6 +338,10 @@ function scripts.epub.make()
if done then
application.report("epub archive made using %s: %s",done,file.join(epubpath,epubfile))
else
+ local list = { }
+ for i=1,#zippers do
+ list[#list+1] = zipper.name
+ end
application.report("no epub archive made, install one of: %s",concat(list," "))
end
diff --git a/scripts/context/lua/mtx-fcd.lua b/scripts/context/lua/mtx-fcd.lua
new file mode 100644
index 000000000..d7e1d17a7
--- /dev/null
+++ b/scripts/context/lua/mtx-fcd.lua
@@ -0,0 +1,366 @@
+if not modules then modules = { } end modules ['mtx-fcd'] = {
+ version = 1.002,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "based on the ruby version from 2005",
+}
+
+-- This is a kind of variant of the good old ncd (norton change directory) program. This
+-- script uses the same indirect cmd trick as Erwin Waterlander's wcd program.
+--
+-- The program is called via the stubs fcd.cmd or fcd.sh. On unix one should probably source
+-- the file: ". fcd args" in order to make the chdir persistent.
+--
+-- You need to create a stub with:
+--
+-- mtxrun --script fcd --stub > fcd.cmd
+-- mtxrun --script fcd --stub > fcd.sh
+--
+-- The stub starts this script and afterwards runs the created directory change script as
+-- part if the same run, so that indeed we change.
+
+local helpinfo = [[
+--clear clear the cache
+--clear --history [entry] clear the history
+--scan clear the cache and add given path(s)
+--add add given path(s)
+--find file given path (can be substring)
+--find --nohistory file given path (can be substring) but don't use history
+--stub print platform stub file
+--list show roots of cached dirs
+--list --history show history of chosen dirs
+--help show this help
+
+usage:
+
+ fcd --scan t:\
+ fcd --add f:\project
+ fcd [--find] whatever
+ fcd --list
+]]
+
+local application = logs.application {
+ name = "mtx-fcd",
+ banner = "Fast Directory Change",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+local writeln = print -- texio.write_nl
+
+local find, char, byte, lower, gsub, format = string.find, string.char, string.byte, string.lower, string.gsub, string.format
+
+local mswinstub = [[@echo off
+
+rem this is: fcd.cmd
+
+@echo off
+
+if not exist "%HOME%" goto homepath
+
+:home
+
+mtxrun --script mtx-fcd.lua %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if exist "%HOME%\mtx-fcd-goto.cmd" call "%HOME%\mtx-fcd-goto.cmd"
+
+goto end
+
+:homepath
+
+if not exist "%HOMEDRIVE%\%HOMEPATH%" goto end
+
+mtxrun --script mtx-fcd.lua %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if exist "%HOMEDRIVE%\%HOMEPATH%\mtx-fcd-goto.cmd" call "%HOMEDRIVE%\%HOMEPATH%\mtx-fcd-goto.cmd"
+
+goto end
+
+:end
+]]
+
+local unixstub = [[#!/usr/bin/env sh
+
+# this is: fcd.sh
+
+# mv fcd.sh fcd
+# chmod fcd 755
+# . fcd [args]
+
+ruby -S fcd_start.rb $1 $2 $3 $4 $5 $6 $7 $8 $9
+
+if test -f "$HOME/fcd_stage.sh" ; then
+ . $HOME/fcd_stage.sh ;
+fi;
+
+]]
+
+local gotofile
+local datafile
+local stubfile
+local stubdata
+local stubdummy
+local stubchdir
+
+if os.platform == 'mswin' then
+ gotofile = 'mtx-fcd-goto.cmd'
+ datafile = 'mtx-fcd-data.lua'
+ stubfile = 'fcd.cmd'
+ stubdata = mswinstub
+ stubdummy = 'rem no dir to change to'
+ stubchdir = 'cd /d "%s"'
+else
+ gotofile = 'mtx-fcd-goto.sh'
+ datafile = 'mtx-fcd-data.lua'
+ stubfile = 'fcd.sh'
+ stubdata = unixstub
+ stubdummy = '# no dir to change to'
+ stubchdir = '# cd "%s"'
+end
+
+local homedir = os.env["HOME"] or "" -- no longer TMP etc
+
+if homedir == "" then
+ homedir = format("%s/%s",os.env["HOMEDRIVE"] or "",os.env["HOMEPATH"] or "")
+end
+
+if homedir == "/" or not lfs.isdir(homedir) then
+ os.exit()
+end
+
+local datafile = file.join(homedir,datafile)
+local gotofile = file.join(homedir,gotofile)
+local hash = nil
+local found = { }
+local pattern = ""
+local version = modules['mtx-fcd'].version
+
+io.savedata(gotofile,stubdummy)
+
+if not lfs.isfile(gotofile) then
+ -- write error
+ os.exit()
+end
+
+local function fcd_clear(onlyhistory,what)
+ if onlyhistory and hash and hash.history then
+ if what and what ~= "" then
+ hash.history[what] = nil
+ else
+ hash.history = { }
+ end
+ else
+ hash = {
+ name = "fcd cache",
+ comment = "generated by mtx-fcd.lua",
+ created = os.date(),
+ version = version,
+ paths = { },
+ history = { },
+ }
+ end
+end
+
+local function fcd_changeto(dir)
+ if dir and dir ~= "" then
+ io.savedata(gotofile,format(stubchdir,dir))
+ end
+end
+
+local function fcd_load(forcecreate)
+ if lfs.isfile(datafile) then
+ hash = dofile(datafile)
+ end
+ if not hash or hash.version ~= version then
+ if forcecache then
+ fcd_clear()
+ else
+ writeln("empty dir cache")
+ fcd_clear()
+ os.exit()
+ end
+ end
+end
+
+local function fcd_save()
+ if hash then
+ io.savedata(datafile,table.serialize(hash,true))
+ end
+end
+
+local function fcd_list(onlyhistory)
+ if hash then
+ writeln("")
+ if onlyhistory then
+ if next(hash.history) then
+ for k, v in table.sortedhash(hash.history) do
+ writeln(format("%s => %s",k,v))
+ end
+ else
+ writeln("no history")
+ end
+ else
+ local paths = hash.paths
+ if #paths > 0 then
+ for i=1,#paths do
+ local path = paths[i]
+ writeln(format("%4i %s",#path[2],path[1]))
+ end
+ else
+ writeln("empty cache")
+ end
+ end
+ end
+end
+
+local function fcd_find()
+ found = { }
+ pattern = environment.files[1] or ""
+ if pattern ~= "" then
+ pattern = string.escapedpattern(pattern)
+ local paths = hash.paths
+ for i=1,#paths do
+ local paths = paths[i][2]
+ for i=1,#paths do
+ local path = paths[i]
+ if find(path,pattern) then
+ found[#found+1] = path
+ end
+ end
+ end
+ end
+end
+
+local function fcd_choose(new)
+ if pattern == "" then
+ writeln(format("staying in dir %q",(gsub(lfs.currentdir(),"\\","/"))))
+ return
+ end
+ if #found == 0 then
+ writeln(format("dir %q not found",pattern))
+ return
+ end
+ local okay = #found == 1 and found[1] or (not new and hash.history[pattern])
+ if okay then
+ writeln(format("changing to %q",okay))
+ fcd_changeto(okay)
+ return
+ end
+ local offset = 0
+ while true do
+ if not found[offset] then
+ offset = 0
+ end
+ io.write("\n")
+ for i=1,26 do
+ local v = found[i+offset]
+ if v then
+ writeln(format("%s %3i %s",char(i+96),offset+i,v))
+ else
+ break
+ end
+ end
+ offset = offset + 26
+ if found[offset+1] then
+ io.write("\n[press enter for more or select letter]\n\n>> ")
+ else
+ io.write("\n[select letter]\n\n>> ")
+ end
+ local answer = lower(io.read() or "")
+ if not answer or answer == 'quit' then
+ break
+ elseif #answer > 0 then
+ local choice = tonumber(answer)
+ if not choice then
+ if answer >= "a" and answer <= "z" then
+ choice = byte(answer) - 96 + offset - 26
+ end
+ end
+ local newdir = found[choice]
+ if newdir then
+ hash.history[pattern] = newdir
+ writeln(format("changing to %q",newdir))
+ fcd_changeto(newdir)
+ fcd_save()
+ return
+ end
+ else
+ -- try again
+ end
+ end
+end
+
+local function globdirs(path,dirs)
+ local dirs = dirs or { }
+ for name in lfs.dir(path) do
+ if not find(name,"%.$") then
+ local fullname = path .. "/" .. name
+ if lfs.isdir(fullname) and not find(fullname,"/%.") then
+ dirs[#dirs+1] = fullname
+ globdirs(fullname,dirs)
+ end
+ end
+ end
+ return dirs
+end
+
+local function fcd_scan()
+ if hash then
+ local paths = hash.paths
+ for i=1,#environment.files do
+ local name = environment.files[i]
+ local name = gsub(name,"\\","/")
+ local name = gsub(name,"/$","")
+ local list = globdirs(name)
+ local done = false
+ for i=1,#paths do
+ if paths[i][1] == name then
+ paths[i][2] = list
+ done = true
+ break
+ end
+ end
+ if not done then
+ paths[#paths+1] = { name, list }
+ end
+ end
+ end
+end
+
+local argument = environment.argument
+
+if argument("clear") then
+ if argument("history") then
+ fcd_load()
+ fcd_clear(true)
+ else
+ fcd_clear()
+ end
+ fcd_save()
+elseif argument("scan") then
+ fcd_clear()
+ fcd_scan()
+ fcd_save()
+elseif argument("add") then
+ fcd_load(true)
+ fcd_scan()
+ fcd_save()
+elseif argument("stub") then
+ writeln(stubdata)
+elseif argument("list") then
+ fcd_load()
+ if argument("history") then
+ fcd_list(true)
+ else
+ fcd_list()
+ end
+elseif argument("help") then
+ application.help()
+else -- also argument("find")
+ fcd_load()
+ fcd_find()
+ fcd_choose(argument("nohistory"))
+end
+
diff --git a/scripts/context/lua/mtx-flac.lua b/scripts/context/lua/mtx-flac.lua
index 37f985654..cb73a6592 100644
--- a/scripts/context/lua/mtx-flac.lua
+++ b/scripts/context/lua/mtx-flac.lua
@@ -6,12 +6,6 @@ if not modules then modules = { } end modules ['mtx-flac'] = {
license = "see context related readme files"
}
--- Written with Within Temptation's "The Unforgiven" in loopmode on
--- the speakers. The following code is also used for my occasional music
--- repository cleanup session using the code below.
-
--- this can become l-flac.lua
-
local sub, match, byte, lower = string.sub, string.match, string.byte, string.lower
local readstring, readnumber = io.readstring, io.readnumber
local concat = table.concat
diff --git a/scripts/context/lua/mtx-fonts.lua b/scripts/context/lua/mtx-fonts.lua
index c5b458c14..31ee18ce9 100644
--- a/scripts/context/lua/mtx-fonts.lua
+++ b/scripts/context/lua/mtx-fonts.lua
@@ -126,7 +126,7 @@ function fonts.names.simple()
end
report("saving names in '%s'",name)
io.savedata(name,table.serialize(simplified,true))
- local data = io.loaddata(resolvers.findfile("font-dum.lua","tex"))
+ local data = io.loaddata(resolvers.findfile("luatex-fonts-syn.lua","tex")) or ""
local dummy = string.match(data,"fonts%.names%.version%s*=%s*([%d%.]+)")
if tonumber(dummy) ~= simpleversion then
report("warning: version number %s in 'font-dum' does not match database version number %s",dummy or "?",simpleversion)
@@ -367,7 +367,7 @@ function scripts.fonts.save()
if name and name ~= "" then
local filename = resolvers.findfile(name) -- maybe also search for opentype
if filename and filename ~= "" then
- local suffix = string.lower(file.extname(filename))
+ local suffix = string.lower(file.suffix(filename))
if suffix == 'ttf' or suffix == 'otf' or suffix == 'ttc' or suffix == "dfont" then
local fontinfo = fontloader.info(filename)
if fontinfo then
diff --git a/scripts/context/lua/mtx-grep.lua b/scripts/context/lua/mtx-grep.lua
index 3cbc1421a..98a97279d 100644
--- a/scripts/context/lua/mtx-grep.lua
+++ b/scripts/context/lua/mtx-grep.lua
@@ -60,7 +60,7 @@ function scripts.grep.find(pattern, files, offset)
if m > 0 then
nofmatches = nofmatches + m
nofmatchedfiles = nofmatchedfiles + 1
- write_nl(format("%s: %s",name,m))
+ write_nl(format("%5i %s",m,name))
io.flush()
end
else
@@ -127,7 +127,7 @@ function scripts.grep.find(pattern, files, offset)
if count and m > 0 then
nofmatches = nofmatches + m
nofmatchedfiles = nofmatchedfiles + 1
- write_nl(format("%s: %s",name,m))
+ write_nl(format("%5i %s",m,name))
io.flush()
end
end
diff --git a/scripts/context/lua/mtx-metapost.lua b/scripts/context/lua/mtx-metapost.lua
index 3b9ed6ff1..44cf8205d 100644
--- a/scripts/context/lua/mtx-metapost.lua
+++ b/scripts/context/lua/mtx-metapost.lua
@@ -49,7 +49,7 @@ local tempname = "mptopdf-temp.tex"
local function do_convert(filename)
if find(filename,".%d+$") or find(filename,"%.mps$") then
io.savedata(tempname,format(template,filename))
- local resultname = format("%s-%s.pdf",file.nameonly(filename),file.extname(filename))
+ local resultname = format("%s-%s.pdf",file.nameonly(filename),file.suffix(filename))
local result = os.execute(format([[context --once --batch --purge --result=%s "%s"]],resultname,tempname))
return lfs.isfile(resultname) and resultname
end
diff --git a/scripts/context/lua/mtx-pdf.lua b/scripts/context/lua/mtx-pdf.lua
index 5654b8bc4..f37ee006a 100644
--- a/scripts/context/lua/mtx-pdf.lua
+++ b/scripts/context/lua/mtx-pdf.lua
@@ -6,14 +6,21 @@ if not modules then modules = { } end modules ['mtx-pdf'] = {
license = "see context related readme files"
}
+local tonumber = tonumber
+local format, gmatch = string.format, string.gmatch
+local utfchar = utf.char
+local concat = table.concat
+local setmetatableindex, sortedhash, sortedkeys = table.setmetatableindex, table.sortedhash, table.sortedkeys
+
local helpinfo = [[
--info show some info about the given file
--metadata show metadata xml blob
+--fonts show used fonts (--detail)
]]
local application = logs.application {
name = "mtx-pdf",
- banner = "ConTeXt PDF Helpers 0.01",
+ banner = "ConTeXt PDF Helpers 0.10",
helpinfo = helpinfo,
}
@@ -39,9 +46,8 @@ local function loadpdffile(filename)
end
end
-function scripts.pdf.info()
- local filename = environment.files[1]
- local pdffile = loadpdffile(filename)
+function scripts.pdf.info(filename)
+ local pdffile = loadpdffile(filename)
if pdffile then
local catalog = pdffile.Catalog
local info = pdffile.Info
@@ -73,9 +79,8 @@ function scripts.pdf.info()
end
end
-function scripts.pdf.metadata()
- local filename = environment.files[1]
- local pdffile = loadpdffile(filename)
+function scripts.pdf.metadata(filename)
+ local pdffile = loadpdffile(filename)
if pdffile then
local catalog = pdffile.Catalog
local metadata = catalog.Metadata
@@ -87,10 +92,127 @@ function scripts.pdf.metadata()
end
end
-if environment.argument("info") then
- scripts.pdf.info()
+local function getfonts(pdffile)
+ local usedfonts = { }
+ for i=1,pdffile.pages.n do
+ local page = pdffile.pages[i]
+ local fontlist = page.Resources.Font
+ for k, v in next, lpdf.epdf.expand(fontlist) do
+ usedfonts[k] = lpdf.epdf.expand(v)
+ end
+ end
+ return usedfonts
+end
+
+local function getunicodes(font)
+ local cid = font.ToUnicode
+ if cid then
+ cid = cid()
+ local counts = { }
+ -- for s in gmatch(cid,"begincodespacerange%s*(.-)%s*endcodespacerange") do
+ -- for a, b in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do
+ -- print(a,b)
+ -- end
+ -- end
+ setmetatableindex(counts, function(t,k) t[k] = 0 return 0 end)
+ for s in gmatch(cid,"beginbfrange%s*(.-)%s*endbfrange") do
+ for first, last, offset in gmatch(s,"<([^>]+)>%s+<([^>]+)>%s+<([^>]+)>") do
+ first = tonumber(first,16)
+ last = tonumber(last,16)
+ offset = tonumber(offset,16)
+ offset = offset - first
+ for i=first,last do
+ local c = i + offset
+ counts[c] = counts[c] + 1
+ end
+ end
+ end
+ for s in gmatch(cid,"beginbfchar%s*(.-)%s*endbfchar") do
+ for old, new in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do
+ for n in gmatch(new,"....") do
+ local c = tonumber(n,16)
+ counts[c] = counts[c] + 1
+ end
+ end
+ end
+ return counts
+ end
+end
+
+function scripts.pdf.fonts(filename)
+ local pdffile = loadpdffile(filename)
+ if pdffile then
+ local usedfonts = getfonts(pdffile)
+ local found = { }
+ for k, v in table.sortedhash(usedfonts) do
+ local counts = getunicodes(v)
+ local codes = { }
+ local chars = { }
+ local freqs = { }
+ if counts then
+ codes = sortedkeys(counts)
+ for i=1,#codes do
+ local k = codes[i]
+ local c = utfchar(k)
+ chars[i] = c
+ freqs[i] = format("U+%05X %s %s",k,counts[k] > 1 and "+" or " ", c)
+ end
+ for i=1,#codes do
+ codes[i] = format("U+%05X",codes[i])
+ end
+ end
+ found[k] = {
+ basefont = v.BaseFont or "no basefont",
+ encoding = v.Encoding or "no encoding",
+ subtype = v.Subtype or "no subtype",
+ unicode = v.ToUnicode and "unicode" or "no unicode",
+ chars = chars,
+ codes = codes,
+ freqs = freqs,
+ }
+ end
+
+ if environment.argument("detail") then
+ for k, v in sortedhash(found) do
+ report("id : %s",k)
+ report("basefont : %s",v.basefont)
+ report("encoding : %s",v.encoding)
+ report("subtype : %s",v.subtype)
+ report("unicode : %s",v.unicode)
+ report("characters : %s", concat(v.chars," "))
+ report("codepoints : %s", concat(v.codes," "))
+ report("")
+ end
+ else
+ local results = { { "id", "basefont", "encoding", "subtype", "unicode", "characters" } }
+ for k, v in sortedhash(found) do
+ results[#results+1] = { k, v.basefont, v.encoding, v.subtype, v.unicode, concat(v.chars," ") }
+ end
+ utilities.formatters.formatcolumns(results)
+ report(results[1])
+ report("")
+ for i=2,#results do
+ report(results[i])
+ end
+ report("")
+ end
+ end
+end
+
+-- scripts.pdf.info("e:/tmp/oeps.pdf")
+-- scripts.pdf.metadata("e:/tmp/oeps.pdf")
+-- scripts.pdf.fonts("e:/tmp/oeps.pdf")
+
+local filename = environment.files[1] or ""
+
+if filename == "" then
+ application.help()
+elseif environment.argument("info") then
+ scripts.pdf.info(filename)
elseif environment.argument("metadata") then
- scripts.pdf.metadata()
+ scripts.pdf.metadata(filename)
+elseif environment.argument("fonts") then
+ scripts.pdf.fonts(filename)
else
application.help()
end
diff --git a/scripts/context/lua/mtx-scite.lua b/scripts/context/lua/mtx-scite.lua
index 116555e79..3369c5f3b 100644
--- a/scripts/context/lua/mtx-scite.lua
+++ b/scripts/context/lua/mtx-scite.lua
@@ -199,14 +199,31 @@ function scripts.scite.words()
if lfs.isfile(txtname) then
report("loading %s",txtname)
local olddata = io.loaddata(txtname) or ""
+ local words = splitwords(olddata)
+ local min, max, n = 100, 1, 0
+ for k, v in next, words do
+ local l = #k
+ if l < min then
+ min = l
+ end
+ if l > max then
+ max = l
+ end
+ n = n + 1
+ end
+ if min > max then
+ min = max
+ end
local newdata = {
- words = splitwords(olddata),
- -- words = olddata,
+ words = words,
source = oldname,
+ min = min,
+ max = max,
+ n = n,
}
- report("saving %s",luaname)
+ report("saving %q, %s words, %s shortest, %s longest",luaname,n,min,max)
io.savedata(luaname,table.serialize(newdata,true))
- report("compiling %s",lucname)
+ report("compiling %q",lucname)
os.execute(format("luac -s -o %s %s",lucname,luaname))
else
report("no data file %s",txtname)
diff --git a/scripts/context/lua/mtx-server-ctx-help.lua b/scripts/context/lua/mtx-server-ctx-help.lua
index a212e1369..39a73dc4e 100644
--- a/scripts/context/lua/mtx-server-ctx-help.lua
+++ b/scripts/context/lua/mtx-server-ctx-help.lua
@@ -15,7 +15,7 @@ dofile(resolvers.findfile("trac-lmx.lua","tex"))
-- problem ... serialize parent stack
-local format = string.format
+local format, match, gsub, find = string.format, string.match, string.gsub, string.find
local concat = table.concat
local report = logs.reporter("ctx-help")
@@ -282,18 +282,48 @@ document.setups.translations = document.setups.translations or {
}
document.setups.formats = {
- open_command = { [[\%s]], [[context.%s (]] },
- close_command = { [[]], [[ )]] },
- connector = { [[]], [[, ]] },
- href_in_list = { [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>%s</a>]], [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>%s</a>]] },
- href_as_command = { [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>\%s</a>]], [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>context.%s</a>]] },
+ open_command = {
+ tex = [[\%s]],
+ lua = [[context.%s (]],
+ },
+ close_command = {
+ tex = [[]],
+ lua = [[ )]],
+ },
+ connector = {
+ tex = [[]],
+ lua = [[, ]],
+ },
+ href_in_list = {
+ tex = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>%s</a>]],
+ lua = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>%s</a>]],
+ },
+ href_as_command = {
+ tex = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>\%s</a>]],
+ lua = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>context.%s</a>]],
+ },
+ modes = {
+ tex = [[<a href='mtx-server-ctx-help.lua?mode=lua'>lua mode</a>]],
+ lua = [[<a href='mtx-server-ctx-help.lua?mode=tex'>tex mode</a>]],
+ },
+ optional_single = {
+ tex = "[optional string %s]",
+ lua = "{optional string %s}",
+ },
+ optional_list = {
+ tex = "[optional list %s]",
+ lua = "{optional table %s}" ,
+ } ,
+ mandate_single = {
+ tex = "[mandate string %s]",
+ lua = "{mandate string %s}",
+ },
+ mandate_list = {
+ tex = "[mandate list %s]",
+ lua = "{mandate list %s}",
+ },
interface = [[<a href='mtx-server-ctx-help.lua?interface=%s&mode=%s'>%s</a>]],
source = [[<a href='mtx-server-ctx-help.lua?source=%s&mode=%s'>%s</a>]],
- modes = { [[<a href='mtx-server-ctx-help.lua?mode=2'>lua mode</a>]], [[<a href='mtx-server-ctx-help.lua?mode=1'>tex mode</a>]] },
- optional_single = { "[optional string %s]", "{optional string %s}" },
- optional_list = { "[optional list %s]", "{optional table %s}" } ,
- mandate_single = { "[mandate string %s]", "{mandate string %s}" },
- mandate_list = { "[mandate list %s]", "{mandate list %s}" },
parameter = [[<tr><td width='15%%'>%s</td><td width='15%%'>%s</td><td width='70%%'>%s</td></tr>]],
parameters = [[<table width='100%%'>%s</table>]],
listing = [[<pre><t>%s</t></listing>]],
@@ -315,7 +345,7 @@ end
local function translated(e,int)
local attributes = e.at
local s = attributes.type or "?"
- local tag = s:match("^cd:(.*)$")
+ local tag = match(s,"^cd:(.*)$")
if attributes.default == "yes" then
return format(document.setups.formats.default,tag or "?")
elseif tag then
@@ -329,7 +359,7 @@ document.setups.loaded = document.setups.loaded or { }
document.setups.current = { }
document.setups.showsources = true
-document.setups.mode = 1
+document.setups.mode = "tex"
function document.setups.load(filename)
filename = resolvers.findfile(filename) or ""
@@ -402,7 +432,7 @@ end
function document.setups.show(name)
local current = document.setups.current
if current.root then
- local name = name:gsub("[<>]","")
+ local name = gsub(name,"[<>]","")
local setup = xml.first(current.root,"cd:command[@name='" .. name .. "']")
current.used[#current.used+1] = setup
xml.sprint(setup)
@@ -452,12 +482,12 @@ function document.setups.collect(name,int,lastmode)
category = attributes.category or "",
}
if document.setups.showsources then
- data.source = (attributes.file and formats.source:format(attributes.file,lastmode,attributes.file)) or ""
+ data.source = (attributes.file and format(formats.source,attributes.file,lastmode,attributes.file)) or ""
else
data.source = attributes.file or ""
end
local n, sequence, tags = 0, { }, { }
- sequence[#sequence+1] = formats.open_command[lastmode]:format(document.setups.csname(command,int))
+ sequence[#sequence+1] = format(formats.open_command[lastmode],document.setups.csname(command,int))
local arguments, tag = { }, ""
for r, d, k in xml.elements(command,"(cd:keywords|cd:assignments)") do
n = n + 1
@@ -470,15 +500,15 @@ function document.setups.collect(name,int,lastmode)
end
if attributes.optional == 'yes' then
if attributes.list == 'yes' then
- tag = formats.optional_list[lastmode]:format(n)
+ tag = format(formats.optional_list[lastmode],n)
else
- tag = formats.optional_single[lastmode]:format(n)
+ tag = format(formats.optional_single[lastmode],n)
end
else
if attributes.list == 'yes' then
- tag = formats.mandate_list[lastmode]:format(n)
+ tag = format(formats.mandate_list[lastmode],n)
else
- tag = formats.mandate_single[lastmode]:format(n)
+ tag = format(formats.mandate_single[lastmode],n)
end
end
sequence[#sequence+1] = tag
@@ -506,7 +536,7 @@ function document.setups.collect(name,int,lastmode)
right[#right+1] = translated(d[k],int)
end
end
- parameters[#parameters+1] = formats.parameter:format(left,"",concat(right, ", "))
+ parameters[#parameters+1] = format(formats.parameter,left,"",concat(right, ", "))
else
local what = tags[n]
for r, d, k in xml.elements(d[k],"(cd:parameter|cd:inherit)") do
@@ -514,11 +544,11 @@ function document.setups.collect(name,int,lastmode)
local left, right = d[k].at.name or "?", { }
if tag == "inherit" then
local name = d[k].at.name or "?"
- local goto = document.setups.formats.href_as_command[lastmode]:format(name,lastmode,name)
- if #parameters > 0 and not parameters[#parameters]:find("<br/>") then
- parameters[#parameters+1] = formats.parameter:format("<br/>","","")
+ local goto = format(document.setups.formats.href_as_command[lastmode],name,lastmode,name)
+ if #parameters > 0 and not find(parameters[#parameters],"<br/>") then
+ parameters[#parameters+1] = format(formats.parameter,"<br/>","","")
end
- parameters[#parameters+1] = formats.parameter:format(what,formats.special:format(translate("inherits",int)),goto)
+ parameters[#parameters+1] = format(formats.parameter,what,format(formats.special,translate("inherits",int)),goto)
else
for r, d, k in xml.elements(d[k],"(cd:constant|cd:resolve)") do
local tag = d[k].tg
@@ -534,15 +564,15 @@ function document.setups.collect(name,int,lastmode)
right[#right+1] = translated(d[k],int)
end
end
- parameters[#parameters+1] = formats.parameter:format(what,left,concat(right, ", "))
+ parameters[#parameters+1] = format(formats.parameter,what,left,concat(right, ", "))
end
what = ""
end
end
- parameters[#parameters+1] = formats.parameter:format("<br/>","","")
+ parameters[#parameters+1] = format(formats.parameter,"<br/>","","")
end
data.parameters = parameters or { }
- data.mode = formats.modes[lastmode or 1]
+ data.mode = formats.modes[lastmode or "tex"]
return data
else
return nil
@@ -566,7 +596,7 @@ local interfaces = {
romanian = 'ro',
}
-local lastinterface, lastcommand, lastsource, lastmode = "en", "", "", 1
+local lastinterface, lastcommand, lastsource, lastmode = "en", "", "", "tex"
local variables = {
['color-background-main-left'] = '#3F3F3F',
@@ -584,78 +614,87 @@ local function doit(configuration,filename,hashed)
local formats = document.setups.formats
- local start = os.clock()
+ local start = os.clock()
+ local detail = hashed.queries
- local detail = url.query(hashed.query or "")
+ if detail then
- lastinterface = detail.interface or lastinterface
- lastcommand = detail.command or lastcommand
- lastsource = detail.source or lastsource
- lastmode = tonumber(detail.mode or lastmode) or 1
+ lastinterface = detail.interface or lastinterface
+ lastcommand = detail.command or lastcommand
+ lastsource = detail.source or lastsource
+ lastmode = detail.mode or lastmode or "tex"
- if lastinterface then
- report("checking interface: %s",lastinterface)
- document.setups.load(format("cont-%s.xml",lastinterface))
- end
+ lastcommand = gsub(lastcommand,"%s*^\\*(.+)%s*","%1")
- local div = document.setups.div[lastinterface]
- local span = document.setups.span[lastinterface]
+ if lastinterface then
+ report("checking interface: %s",lastinterface)
+ document.setups.load(format("cont-%s.xml",lastinterface))
+ end
- local result = { content = "error" }
+ local div = document.setups.div [lastinterface]
+ local span = document.setups.span[lastinterface]
- local names, refs, ints = document.setups.names(lastinterface), { }, { }
- for k=1,#names do
- local v = names[k]
- refs[k] = formats.href_in_list[lastmode]:format(v[1],lastmode,v[2])
- end
- if lastmode ~= 2 then
- local sorted = table.sortedkeys(interfaces)
- for k=1,#sorted do
- local v = sorted[k]
- ints[k] = formats.interface:format(interfaces[v],lastmode,v)
+ local names, refs, ints = document.setups.names(lastinterface), { }, { }
+ for k=1,#names do
+ local v = names[k]
+ refs[k] = format(formats.href_in_list[lastmode],v[1],lastmode,v[2])
+ end
+ if lastmode ~= "lua" then
+ local sorted = table.sortedkeys(interfaces)
+ for k=1,#sorted do
+ local v = sorted[k]
+ ints[k] = format(formats.interface,interfaces[v],lastmode,v)
+ end
end
- end
- local n = concat(refs,"<br/>")
- local i = concat(ints,"<br/><br/>")
+ local n = concat(refs,"<br/>")
+ local i = concat(ints,"<br/><br/>")
- if div then
- variables.names = div:format(n)
- variables.interfaces = div:format(i)
- else
- variables.names = n
- variables.interfaces = i
- end
+ if div then
+ variables.names = format(div,n)
+ variables.interfaces = format(div,i)
+ else
+ variables.names = n
+ variables.interfaces = i
+ end
- -- first we need to add information about mkii/mkiv
-
- variables.maintitle = "no definition"
- variables.maintext = ""
- variables.extra = ""
-
- if document.setups.showsources and lastsource and lastsource ~= "" then
- -- todo: mkii, mkiv, tex (can be different)
- local data = io.loaddata(resolvers.findfile(lastsource))
- variables.maintitle = lastsource
- variables.maintext = formats.listing:format(data)
- lastsource = ""
- elseif lastcommand and lastcommand ~= "" then
- local data = document.setups.collect(lastcommand,lastinterface,lastmode)
- if data then
- local what, extra = { "environment", "category", "source", "mode" }, { }
- for k=1,#what do
- local v = what[k]
- if data[v] and data[v] ~= "" then
- lmx.set(v, data[v])
- extra[#extra+1] = v .. ": " .. data[v]
+ -- first we need to add information about mkii/mkiv
+
+ variables.maintitle = "no definition"
+ variables.maintext = ""
+ variables.extra = ""
+
+ if document.setups.showsources and lastsource and lastsource ~= "" then
+ -- todo: mkii, mkiv, tex (can be different)
+ local data = io.loaddata(resolvers.findfile(lastsource))
+ variables.maintitle = lastsource
+ variables.maintext = format(formats.listing,data)
+ lastsource = ""
+ elseif lastcommand and lastcommand ~= "" then
+ local data = document.setups.collect(lastcommand,lastinterface,lastmode)
+ if data then
+ local what, extra = { "environment", "category", "source", "mode" }, { }
+ for k=1,#what do
+ local v = what[k]
+ if data[v] and data[v] ~= "" then
+ lmx.set(v, data[v])
+ extra[#extra+1] = v .. ": " .. data[v]
+ end
end
+ variables.maintitle = data.sequence
+ variables.maintext = format(formats.parameters,concat(data.parameters))
+ variables.extra = concat(extra,"&nbsp;&nbsp;&nbsp;")
+ else
+ variables.maintext = "select command"
end
- variables.maintitle = data.sequence
- variables.maintext = formats.parameters:format(concat(data.parameters))
- variables.extra = concat(extra,"&nbsp;&nbsp;&nbsp;")
- else
- variables.maintext = "select command"
end
+
+ else
+
+ variables.maintitle = "no definition"
+ variables.maintext = "some error"
+ variables.extra = ""
+
end
local content = lmx.convert('context-help.lmx',false,variables)
diff --git a/scripts/context/lua/mtx-server.lua b/scripts/context/lua/mtx-server.lua
index 068d51111..d6e8ac902 100644
--- a/scripts/context/lua/mtx-server.lua
+++ b/scripts/context/lua/mtx-server.lua
@@ -30,7 +30,7 @@ dofile(resolvers.findfile("l-url.lua","tex"))
dofile(resolvers.findfile("luat-soc.lua","tex"))
local socket = socket or require("socket")
-local http = socket or require("socket.http")
+local http = http or require("socket.http") -- not needed
local format = string.format
-- The following two lists are taken from webrick (ruby) and
@@ -231,6 +231,7 @@ function handlers.lua(client,configuration,filename,suffix,iscontent,hashed) --
end
if result then
if type(result) == "function" then
+ report("running script: %s",filename)
result = result(configuration,filename,hashed) -- second argument will become query
end
if result and type(result) == "string" then
@@ -242,7 +243,7 @@ function handlers.lua(client,configuration,filename,suffix,iscontent,hashed) --
local action = handlers[suffix] or handlers.generic
action(client,configuration,result.content,suffix,true) -- content
elseif result.filename then
- local suffix = file.extname(result.filename) or "text/html"
+ local suffix = file.suffix(result.filename) or "text/html"
local action = handlers[suffix] or handlers.generic
action(client,configuration,result.filename,suffix,false) -- filename
else
@@ -301,40 +302,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 }
- while true do -- no multiple clients
+ local script = configuration.script
+ while true do -- blocking
local start = os.clock()
--- 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/.*$") or "" -- todo: more clever / post
+ report("request data: %s",tostring(request))
+ local fullurl = string.match(request,"GET (.+) HTTP/.*$") or "" -- todo: more clever / post
if fullurl == "" then
+ report("no url")
errormessage(client,configuration,404)
else
- fullurl = socket.url.unescape(fullurl)
+ report("requested url: %s",fullurl)
+ fullurl = socket.url.unescape(fullurl) -- still needed?
local hashed = url.hashed(fullurl)
local query = url.query(hashed.query)
- local filename = hashed.path
--- table.print(hashed)
- if filename then
+ local filename = hashed.path -- hm, not query?
+ if script then
+ filename = script
+ report("forced script: %s",filename)
+ local suffix = file.suffix(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
+ elseif filename then
filename = socket.url.unescape(filename)
report("requested action: %s",filename)
- if filename:find("%.%.") then
+ if string.find(filename,"%.%.") 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 suffix = file.suffix(filename)
local action = handlers[suffix] or handlers.generic
if action then
report("performing action: %s",filename)
@@ -358,6 +369,7 @@ if environment.argument("auto") then
port = environment.argument("port"),
root = environment.argument("root") or file.dirname(path) or ".",
scripts = environment.argument("scripts") or file.dirname(path) or ".",
+ script = environment.argument("script"),
}
elseif environment.argument("start") then
scripts.webserver.run {
@@ -365,6 +377,7 @@ elseif environment.argument("start") then
root = environment.argument("root") or ".", -- "e:/websites/www.pragma-ade.com",
index = environment.argument("index"),
scripts = environment.argument("scripts"),
+ script = environment.argument("script"),
}
else
application.help()
diff --git a/scripts/context/lua/mtx-tools.lua b/scripts/context/lua/mtx-tools.lua
index 45961a639..c1aaf9e5d 100644
--- a/scripts/context/lua/mtx-tools.lua
+++ b/scripts/context/lua/mtx-tools.lua
@@ -102,7 +102,7 @@ end
function scripts.tools.dirtoxml()
- local join, removesuffix, extname, date = file.join, file.removesuffix, file.extname, os.date
+ local join, removesuffix, suffixonly, date = file.join, file.removesuffix, file.suffixonly, os.date
local xmlns = "http://www.pragma-ade.com/rlg/xmldir.rng"
local timestamp = "%Y-%m-%d %H:%M"
diff --git a/scripts/context/lua/mtx-update.lua b/scripts/context/lua/mtx-update.lua
index 037de8650..b5f34d615 100644
--- a/scripts/context/lua/mtx-update.lua
+++ b/scripts/context/lua/mtx-update.lua
@@ -421,9 +421,9 @@ function scripts.update.synchronize()
if platform == 'mswin' then
bin = gsub(bin,"([a-zA-Z]):/", "/cygdrive/%1/")
texroot = gsub(texroot,"([a-zA-Z]):/", "/cygdrive/%1/")
- command = format("%s -t %s/texmf-context/scripts/context/lua/%s.lua %s/texmf-mswin/bin/", bin, texroot, script, texroot)
+ command = format([[%s -t "%s/texmf-context/scripts/context/lua/%s.lua" "%s/texmf-mswin/bin/"]], bin, texroot, script, texroot)
else
- command = format("%s -tgo --chmod=a+x %s/texmf-context/scripts/context/lua/%s.lua %s/texmf-%s/bin/%s", bin, texroot, script, texroot, platform, script)
+ command = format([[%s -tgo --chmod=a+x '%s/texmf-context/scripts/context/lua/%s.lua' '%s/texmf-%s/bin/%s']], bin, texroot, script, texroot, platform, script)
end
report("updating %s for %s: %s", script, platform, command)
scripts.update.run(command)
diff --git a/scripts/context/lua/mtx-watch.lua b/scripts/context/lua/mtx-watch.lua
index 36a3176c4..31ed95f7b 100644
--- a/scripts/context/lua/mtx-watch.lua
+++ b/scripts/context/lua/mtx-watch.lua
@@ -227,17 +227,6 @@ function scripts.watch.watch()
end
end
local n, start = 0, time()
---~ local function wait()
---~ io.flush()
---~ if not done then
---~ n = n + 1
---~ if n >= 10 then
---~ report("run time: %i seconds, memory usage: %0.3g MB", difftime(time(),start), (status.luastate_bytes/1024)/1000)
---~ n = 0
---~ end
---~ os.sleep(delay)
---~ end
---~ end
local wtime = 0
local function wait()
io.flush()
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index 108f2a8a1..e6bbbe2b5 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -8,6 +8,11 @@ if not modules then modules = { } end modules ['mtxrun'] = {
license = "see context related readme files"
}
+-- if not lpeg then require("lpeg") end
+-- if not md5 then require("md5") end
+-- if not lfs then require("lfs") end
+-- if not texconfig then texconfig = { } end
+
-- one can make a stub:
--
-- #!/bin/sh
@@ -150,11 +155,28 @@ function string.topattern(str,lowercase,strict)
end
end
+
+function string.valid(str,default)
+ return (type(str) == "string" and str ~= "" and str) or default or nil
+end
+
-- obsolete names:
string.quote = string.quoted
string.unquote = string.unquoted
+-- handy fallback
+
+string.itself = function(s) return s end
+
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -168,7 +190,8 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string
+local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local table, string = table, string
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
@@ -179,6 +202,8 @@ local getinfo = debug.getinfo
-- impact on ConTeXt was not that large; the remaining ipairs already
-- have been replaced. In a similar fashion we also hardly used pairs.
--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -238,12 +263,16 @@ function table.strip(tab)
end
function table.keys(t)
- local keys, k = { }, 0
- for key, _ in next, t do
- k = k + 1
- keys[k] = key
+ if t then
+ local keys, k = { }, 0
+ for key, _ in next, t do
+ k = k + 1
+ keys[k] = key
+ end
+ return keys
+ else
+ return { }
end
- return keys
end
local function compare(a,b)
@@ -256,41 +285,49 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
- for key,_ in next, tab do
- s = s + 1
- srt[s] = key
- if category == 3 then
- -- no further check
- else
- local tkey = type(key)
- if tkey == "string" then
- category = (category == 2 and 3) or 1
- elseif tkey == "number" then
- category = (category == 1 and 3) or 2
+ if tab then
+ local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ for key,_ in next, tab do
+ s = s + 1
+ srt[s] = key
+ if category == 3 then
+ -- no further check
else
- category = 3
+ local tkey = type(key)
+ if tkey == "string" then
+ category = (category == 2 and 3) or 1
+ elseif tkey == "number" then
+ category = (category == 1 and 3) or 2
+ else
+ category = 3
+ end
end
end
- end
- if category == 0 or category == 3 then
- sort(srt,compare)
+ if category == 0 or category == 3 then
+ sort(srt,compare)
+ else
+ sort(srt)
+ end
+ return srt
else
- sort(srt)
+ return { }
end
- return srt
end
local function sortedhashkeys(tab) -- fast one
- local srt, s = { }, 0
- for key,_ in next, tab do
- if key then
- s= s + 1
- srt[s] = key
+ if tab then
+ local srt, s = { }, 0
+ for key,_ in next, tab do
+ if key then
+ s= s + 1
+ srt[s] = key
+ end
end
+ sort(srt)
+ return srt
+ else
+ return { }
end
- sort(srt)
- return srt
end
table.sortedkeys = sortedkeys
@@ -315,7 +352,7 @@ end
table.sortedhash = sortedhash
table.sortedpairs = sortedhash
-function table.append(t, list)
+function table.append(t,list)
local n = #t
for i=1,#list do
n = n + 1
@@ -550,12 +587,26 @@ local function do_serialize(root,name,depth,level,indexed)
end
-- we could check for k (index) being number (cardinal)
if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- if compact then
+ -- -- NOT: for k=1,#root do (we need to quit at nil)
+ -- for k,v in ipairs(root) do -- can we use next?
+ -- if not first then first = k end
+ -- last = last + 1
+ -- end
+ -- end
+ local first, last = nil, 0
if compact then
- -- NOT: for k=1,#root do (we need to quit at nil)
- for k,v in ipairs(root) do -- can we use next?
- if not first then first = k end
- last = last + 1
+ last = #root
+ for k=1,last do
+-- if not root[k] then
+ if root[k] == nil then
+ last = k - 1
+ break
+ end
+ end
+ if last > 0 then
+ first = 1
end
end
local sk = sortedkeys(root)
@@ -1027,23 +1078,27 @@ function table.reversed(t)
end
end
-function table.sequenced(t,sep,simple) -- hash only
- local s, n = { }, 0
- for k, v in sortedhash(t) do
- if simple then
- if v == true then
- n = n + 1
- s[n] = k
- elseif v and v~= "" then
+function table.sequenced(t,sep) -- hash only
+ if t then
+ local s, n = { }, 0
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ n = n + 1
+ s[n] = k
+ elseif v and v~= "" then
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
+ end
+ else
n = n + 1
s[n] = k .. "=" .. tostring(v)
end
- else
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
end
+ return concat(s, sep or " | ")
+ else
+ return ""
end
- return concat(s, sep or " | ")
end
function table.print(t,...)
@@ -1124,6 +1179,8 @@ local lpeg = require("lpeg")
-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+-- some code will move to unicode and string
+
local report = texio and texio.write_nl or print
-- local lpmatch = lpeg.match
@@ -1160,8 +1217,8 @@ local report = texio and texio.write_nl or print
-- 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
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-- 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.
@@ -1169,9 +1226,8 @@ local byte, char, gmatch = string.byte, string.char, string.gmatch
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 P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
local utfcharacters = string.utfcharacters
local utfgmatch = unicode and unicode.utf8.gmatch
@@ -1222,6 +1278,10 @@ patterns.utf8char = utf8char
patterns.validutf8 = validutf8char
patterns.validutf8char = validutf8char
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+
patterns.digit = digit
patterns.sign = sign
patterns.cardinal = sign^0 * digit^1
@@ -1241,16 +1301,16 @@ 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.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
patterns.newline = newline
patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.nonspacer = 1 - spacer
+patterns.nonwhitespace = 1 - whitespace
patterns.equal = P("=")
patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.commaspacer = P(",") * spacer^0
patterns.period = P(".")
patterns.colon = P(":")
patterns.semicolon = P(";")
@@ -1265,6 +1325,10 @@ patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
@@ -1275,8 +1339,17 @@ patterns.beginline = #(1-newline)
-- 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?
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
end
function lpeg.splitter(pattern, action)
@@ -1325,7 +1398,7 @@ function string.splitup(str,separator)
if not separator then
separator = ","
end
- return match(splitters_m[separator] or splitat(separator),str)
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
end
@@ -1337,16 +1410,20 @@ function lpeg.split(separator,str)
c = tsplitat(separator)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
end
- return match(c,str)
end
local spacing = patterns.spacer^0 * newline -- sort of strip
@@ -1362,7 +1439,7 @@ local linesplitter = tsplitat(newline)
patterns.linesplitter = linesplitter
function string.splitlines(str)
- return match(linesplitter,str)
+ return lpegmatch(linesplitter,str)
end
local utflinesplitter = utfbom^-1 * tsplitat(newline)
@@ -1370,7 +1447,58 @@ local utflinesplitter = utfbom^-1 * tsplitat(newline)
patterns.utflinesplitter = utflinesplitter
function string.utfsplitlines(str)
- return match(utflinesplitter,str or "")
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
+local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
+
+function string.utfsplit(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+-- inspect(string.utfsplit("a b c d"))
+-- inspect(string.utfsplit("a b c d",true))
+
+-- -- alternative 1: 0.77
+--
+-- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
+--
+-- function string.utflength(str)
+-- return #lpegmatch(utfcharcounter,str or "")
+-- end
+--
+-- -- alternative 2: 1.70
+--
+-- local n = 0
+--
+-- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
+--
+-- function string.utflength(str)
+-- n = 0
+-- lpegmatch(utfcharcounter,str or "")
+-- return n
+-- end
+--
+-- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+local n = 0
+
+local utfcharcounter = utfbom^-1 * Cs ( (
+ Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+)^0 )
+
+function string.utflength(str)
+ n = 0
+ lpegmatch(utfcharcounter,str or "")
+ return n
end
@@ -1384,7 +1512,7 @@ function lpeg.checkedsplit(separator,str)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.checkedsplit(str,separator)
@@ -1395,7 +1523,7 @@ function string.checkedsplit(str,separator)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
@@ -1440,11 +1568,11 @@ function lpeg.keeper(str)
end
function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
+ return (P(str) + P(true)) * Cs(anything^0)
end
function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
+ return Cs((1 - P(str) * endofstring)^0)
end
-- Just for fun I looked at the used bytecode and
@@ -1453,8 +1581,22 @@ end
function lpeg.replacer(one,two)
if type(one) == "table" then
local no = #one
- if no > 0 then
- local p
+ local p
+ if no == 0 then
+ for k, v in next, one do
+ local pp = P(k) / v
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ return Cs(((1-one)^1 + one/two)^0)
+ else
for i=1,no do
local o = one[i]
local pp = P(o[1]) / o[2]
@@ -1467,11 +1609,16 @@ function lpeg.replacer(one,two)
return Cs((p + 1)^0)
end
else
+ one = P(one)
two = two or ""
- return Cs((P(one)/two + 1)^0)
+ return Cs(((1-one)^1 + one/two)^0)
end
end
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -1506,7 +1653,7 @@ local nany = utf8char/""
function lpeg.counter(pattern)
pattern = Cs((P(pattern)/" " + nany)^0)
return function(str)
- return #match(pattern,str)
+ return #lpegmatch(pattern,str)
end
end
@@ -1520,7 +1667,7 @@ if utfgmatch then
end
return n
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -1535,9 +1682,9 @@ else
p = Cs((P(what)/" " + nany)^0)
cache[p] = p
end
- return #match(p,str)
+ return #lpegmatch(p,str)
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -1564,7 +1711,7 @@ 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)
+ return lpegmatch(simple and s or p,str)
end
-- utf extensies
@@ -1611,7 +1758,7 @@ else
p = P(uc)
end
end
- match((utf8char/f)^0,str)
+ lpegmatch((utf8char/f)^0,str)
return p
end
@@ -1627,7 +1774,7 @@ function lpeg.UR(str,more)
first = str
last = more or first
else
- first, last = match(range,str)
+ first, last = lpegmatch(range,str)
if not last then
return P(str)
end
@@ -1654,11 +1801,15 @@ end
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
if type(list) ~= "table" then
list = { list, ... }
end
- -- sort(list) -- longest match first
+ -- table.sort(list) -- longest match first
local p = P(list[1])
for l=2,#list do
p = p + P(list[l])
@@ -1666,10 +1817,6 @@ function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
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.
@@ -1827,6 +1974,24 @@ end
-- utfchar(0x205F), -- math thinspace
-- } )
+-- handy from within tex:
+
+local lpegmatch = lpeg.match
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- strips leading and trailing spaces and collapsed all other spaces
+
+local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
+
+function string.collapsespaces(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -1851,14 +2016,14 @@ else
io.fileseparator, io.pathseparator = "/" , ":"
end
-function io.loaddata(filename,textmode)
+function io.loaddata(filename,textmode) -- return nil if empty
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
local data = f:read('*all')
f:close()
- return data
- else
- return nil
+ if #data > 0 then
+ return data
+ end
end
end
@@ -1880,6 +2045,45 @@ function io.savedata(filename,data,joiner)
end
end
+function io.loadlines(filename,n) -- return nil if empty
+ local f = io.open(filename,'r')
+ if f then
+ if n then
+ local lines = { }
+ for i=1,n do
+ local line = f:read("*lines")
+ if line then
+ lines[#lines+1] = line
+ else
+ break
+ end
+ end
+ f:close()
+ lines = concat(lines,"\n")
+ if #lines > 0 then
+ return lines
+ end
+ else
+ local line = f:read("*line") or ""
+ assert(f:close())
+ if #line > 0 then
+ return line
+ end
+ end
+ end
+end
+
+function io.loadchunk(filename,n)
+ local f = io.open(filename,'rb')
+ if f then
+ local data = f:read(n or 1024)
+ f:close()
+ if #data > 0 then
+ return data
+ end
+ end
+end
+
function io.exists(filename)
local f = io.open(filename)
if f == nil then
@@ -2107,7 +2311,7 @@ if not modules then modules = { } end modules ['l-number'] = {
-- this module will be replaced when we have the bit library
-local tostring = tostring
+local tostring, tonumber = tostring, tonumber
local format, floor, match, rep = string.format, math.floor, string.match, string.rep
local concat, insert = table.concat, table.insert
local lpegmatch = lpeg.match
@@ -2170,11 +2374,11 @@ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
end
function number.setbit(x, p)
- return hasbit(x, p) and x or x + p
+ return (x % (p + p) >= p) and x or x + p
end
function number.clearbit(x, p)
- return hasbit(x, p) and x - p or x
+ return (x % (p + p) >= p) and x - p or x
end
@@ -2208,6 +2412,10 @@ function number.tobitstring(n,m)
end
+function number.valid(str,default)
+ return tonumber(str) or default or nil
+end
+
end -- of closure
@@ -2319,17 +2527,28 @@ if not modules then modules = { } end modules ['l-os'] = {
-- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
-- os.platform : extended os.name with architecture
+-- os.sleep() => socket.sleep()
+-- math.randomseed(tonumber(string.sub(string.reverse(tostring(math.floor(socket.gettime()*10000))),1,6)))
+
-- maybe build io.flush in os.execute
local os = os
+local date, time = os.date, os.time
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
+local random, ceil, randomseed = math.random, math.ceil, math.randomseed
+local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring
-- The following code permits traversing the environment table, at least
-- in luatex. Internally all environment names are uppercase.
+-- The randomseed in Lua is not that random, although this depends on the operating system as well
+-- as the binary (Luatex is normally okay). But to be sure we set the seed anyway.
+
+math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+
+randomseed(math.initialseed)
+
if not os.__getenv__ then
os.__getenv__ = os.getenv
@@ -2433,12 +2652,14 @@ else
os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
+local launchers = {
+ windows = "start %s",
+ macosx = "open %s",
+ unix = "$BROWSER %s &> /dev/null &",
+}
+
function os.launch(str)
- if os.type == "windows" then
- os.execute("start " .. str) -- os.spawn ?
- else
- os.execute(str .. " &") -- os.spawn ?
- end
+ os.execute(format(launchers[os.name] or launchers.unix,str))
end
if not os.times then
@@ -2649,7 +2870,7 @@ end
local d
function os.timezone(delta)
- d = d or tonumber(tonumber(os.date("%H")-os.date("!%H")))
+ d = d or tonumber(tonumber(date("%H")-date("!%H")))
if delta then
if d > 0 then
return format("+%02i:00",d)
@@ -2661,6 +2882,44 @@ function os.timezone(delta)
end
end
+local timeformat = format("%%s%s",os.timezone(true))
+local dateformat = "!%Y-%m-%d %H:%M:%S"
+
+function os.fulltime(t,default)
+ t = tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = nil
+ end
+ return format(timeformat,date(dateformat,t))
+end
+
+local dateformat = "%Y-%m-%d %H:%M:%S"
+
+function os.localtime(t,default)
+ t = tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = nil
+ end
+ return date(dateformat,t)
+end
+
+function os.converttime(t,default)
+ local t = tonumber(t)
+ if t and t > 0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
+end
+
local memory = { }
local function which(filename)
@@ -2735,7 +2994,7 @@ local function nameonly(name)
return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$",""))
end
-local function extname(name,default)
+local function suffixonly(name,default)
return match(name,"^.+%.([^/\\]-)$") or default or ""
end
@@ -2744,11 +3003,16 @@ local function splitname(name)
return n or name, s or ""
end
-file.basename = basename
-file.dirname = dirname
-file.nameonly = nameonly
-file.extname = extname
-file.suffix = extname
+file.basename = basename
+
+file.pathpart = dirname
+file.dirname = dirname
+
+file.nameonly = nameonly
+
+file.suffixonly = suffixonly
+file.extname = suffixonly -- obsolete
+file.suffix = suffixonly
function file.removesuffix(filename)
return (gsub(filename,"%.[%a%d]+$",""))
@@ -2864,6 +3128,11 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
+function file.size(name)
+ local a = attributes(name)
+ return a and a.size or 0
+end
+
-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -3001,6 +3270,7 @@ local drive = C(R("az","AZ")) * P(":")
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 rest = C(P(1)^0)
drive = drive + Cc("")
path = path + Cc("")
@@ -3009,7 +3279,8 @@ 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)
+local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures
+local pattern_d = path * rest
function file.splitname(str,splitdrive)
if splitdrive then
@@ -3019,6 +3290,10 @@ function file.splitname(str,splitdrive)
end
end
+function file.splitbase(str)
+ return lpegmatch(pattern_d,str) -- returns path, base+suffix
+end
+
function file.nametotable(str,splitdrive) -- returns table
local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
if splitdrive then
@@ -3040,6 +3315,8 @@ function file.nametotable(str,splitdrive) -- returns table
end
end
+-- print(file.splitbase("a/b/c.txt"))
+
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
--
-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
@@ -3081,15 +3358,30 @@ if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
-function file.needs_updating(oldname,newname,threshold) -- size modification access change
- local oldtime = lfs.attributes(oldname, modification)
- local newtime = lfs.attributes(newname, modification)
- if newtime >= oldtime then
- return false
- elseif oldtime - newtime < (threshold or 1) then
- return false
+function file.needsupdating(oldname,newname,threshold) -- size modification access change
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime = lfs.attributes(newname,"modification")
+ if not newtime then
+ return true -- no new file, so no updating needed
+ elseif newtime >= oldtime then
+ return false -- new file definitely needs updating
+ elseif oldtime - newtime < (threshold or 1) then
+ return false -- new file is probably still okay
+ else
+ return true -- new file has to be updated
+ end
else
- return true
+ return false -- no old file, so no updating needed
+ end
+end
+
+file.needs_updating = file.needsupdating
+
+function file.syncmtimes(oldname,newname)
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
end
end
@@ -3111,7 +3403,7 @@ function file.loadchecksum(name)
return nil
end
-function file.savechecksum(name, checksum)
+function file.savechecksum(name,checksum)
if not checksum then checksum = file.checksum(name) end
if checksum then
io.savedata(name .. ".md5",checksum)
@@ -3136,7 +3428,7 @@ if not modules then modules = { } end modules ['l-url'] = {
local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find
local concat = table.concat
local tonumber, type = tonumber, type
-local P, C, R, S, Cs, Cc, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct
+local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V
local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer
-- from wikipedia:
@@ -3169,15 +3461,19 @@ local endofstring = P(-1)
local hexdigit = R("09","AF","af")
local plus = P("+")
local nothing = Cc("")
-local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
+local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar
+local escaped = (plus / " ") + escapedchar
-- 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
+--
+-- maybe we should already split the query (better for unescaping as = & can be part of a value
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)
+----- querystr = Cs((escaped+(1- hash))^0)
+local querystr = Cs(( (1- hash))^0)
local fragmentstr = Cs((escaped+(1- endofstring))^0)
local scheme = schemestr * colon + nothing
@@ -3192,11 +3488,20 @@ local parser = Ct(validurl)
lpegpatterns.url = validurl
lpegpatterns.urlsplitter = parser
-local escapes = { } ; for i=0,255 do escapes[i] = format("%%%02X",i) end
+local escapes = { }
+
+setmetatable(escapes, { __index = function(t,k)
+ local v = format("%%%02X",byte(k))
+ t[k] = v
+ return v
+end })
-local escaper = Cs((R("09","AZ","az") + S("-./_") + P(1) / escapes)^0)
+local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most
+local unescaper = Cs((escapedchar + 1)^0)
-lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaped = escapedchar
+lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaper = unescaper
-- todo: reconsider Ct as we can as well have five return values (saves a table)
-- so we can have two parsers, one with and one without
@@ -3208,8 +3513,12 @@ end
local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
local function hasscheme(str)
- local scheme = lpegmatch(isscheme,str) -- at least one character
- return scheme ~= "" and scheme or false
+ if str then
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
+ else
+ return false
+ end
end
@@ -3228,10 +3537,32 @@ local rootbased = P("/")
local barswapper = replacer("|",":")
local backslashswapper = replacer("\\","/")
+-- queries:
+
+local equal = P("=")
+local amp = P("&")
+local key = Cs(((escapedchar+1)-equal )^0)
+local value = Cs(((escapedchar+1)-amp -endofstring)^0)
+
+local splitquery = Cf ( Ct("") * P { "sequence",
+ sequence = V("pair") * (amp * V("pair"))^0,
+ pair = Cg(key * equal * value),
+}, rawset)
+
+-- hasher
+
local function hashed(str) -- not yet ok (/test?test)
+ if str == "" then
+ return {
+ scheme = "invalid",
+ original = str,
+ }
+ end
local s = split(str)
- local somescheme = s[1] ~= ""
- local somequery = s[4] ~= ""
+ local rawscheme = s[1]
+ local rawquery = s[4]
+ local somescheme = rawscheme ~= ""
+ local somequery = rawquery ~= ""
if not somescheme and not somequery then
s = {
scheme = "file",
@@ -3247,14 +3578,17 @@ local function hashed(str) -- not yet ok (/test?test)
local authority, path, filename = s[2], s[3]
if authority == "" then
filename = path
+ elseif path == "" then
+ filename = ""
else
filename = authority .. "/" .. path
end
s = {
- scheme = s[1],
+ scheme = rawscheme,
authority = authority,
path = path,
- query = s[4],
+ query = lpegmatch(unescaper,rawquery), -- unescaped, but possible conflict with & and =
+ queries = lpegmatch(splitquery,rawquery), -- split first and then unescaped
fragment = s[5],
original = str,
noscheme = false,
@@ -3264,6 +3598,8 @@ local function hashed(str) -- not yet ok (/test?test)
return s
end
+-- inspect(hashed("template://test"))
+
-- Here we assume:
--
-- files: /// = relative
@@ -3306,23 +3642,65 @@ function url.construct(hash) -- dodo: we need to escape !
return lpegmatch(escaper,concat(fullurl))
end
-function url.filename(filename)
+function url.filename(filename) -- why no lpeg here ?
local t = hashed(filename)
return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename
end
+local function escapestring(str)
+ return lpegmatch(escaper,str)
+end
+
+url.escape = escapestring
+
+-- function url.query(str) -- separator could be an option
+-- if type(str) == "string" then
+-- local t = { }
+-- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
+-- t[k] = v
+-- end
+-- return t
+-- else
+-- return str
+-- end
+-- end
+
function url.query(str)
if type(str) == "string" then
- local t = { }
- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
- t[k] = v
- end
- return t
+ return lpegmatch(splitquery,str) or ""
else
return str
end
end
+function url.toquery(data)
+ local td = type(data)
+ if td == "string" then
+ return #str and escape(data) or nil -- beware of double escaping
+ elseif td == "table" then
+ if next(data) then
+ local t = { }
+ for k, v in next, data do
+ t[#t+1] = format("%s=%s",k,escapestring(v))
+ end
+ return concat(t,"&")
+ end
+ else
+ -- nil is a signal that no query
+ end
+end
+
+-- /test/ | /test | test/ | test => test
+
+function url.barepath(path)
+ if not path or path == "" then
+ return ""
+ else
+ return (gsub(path,"^/?(.-)/?$","%1"))
+ end
+end
+
+
@@ -3363,6 +3741,24 @@ local isdir = lfs.isdir
local isfile = lfs.isfile
local currentdir = lfs.currentdir
+-- in case we load outside luatex
+
+if not isdir then
+ function isdir(name)
+ local a = attributes(name)
+ return a and a.mode == "directory"
+ end
+ lfs.isdir = isdir
+end
+
+if not isfile then
+ function isfile(name)
+ local a = attributes(name)
+ return a and a.mode == "file"
+ end
+ lfs.isfile = isfile
+end
+
-- handy
function dir.current()
@@ -3738,28 +4134,49 @@ function boolean.tonumber(b)
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
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
elseif str == "true" then
return true
elseif str == "false" then
return false
+ elseif not tolerant then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
else
- return str
+ return str == "yes" or str == "on" or str == "t"
end
end
string.toboolean = toboolean
+function string.booleanstring(str)
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
+ else
+ return str == "yes" or str == "on" or str == "t"
+ end
+end
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -3784,57 +4201,229 @@ if not modules then modules = { } end modules ['l-unicode'] = {
license = "see context related readme files"
}
+-- this module will be reorganized
+
+-- todo: utf.sub replacement (used in syst-aux)
+
+local concat = table.concat
+local type = type
+local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local utftype = patterns.utftype
+local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
+local utfsplitlines = string.utfsplitlines
+
if not unicode then
- unicode = { utf8 = { } }
+ unicode = { }
+
+end
+
+local unicode = unicode
+
+utf = utf or unicode.utf8
+
+if not utf then
+
+ utf8 = { }
+ unicode.utf8 = utf8
+ utf = utf8
+
+end
+
+if not utf.char then
local floor, char = math.floor, string.char
- function unicode.utf8.utfchar(n)
+ function utf.char(n)
if n < 0x80 then
+ -- 0aaaaaaa : 0x80
return char(n)
elseif n < 0x800 then
+ -- 110bbbaa : 0xC0 : n >> 6
+ -- 10aaaaaa : 0x80 : n & 0x3F
return char(
0xC0 + floor(n/0x40),
0x80 + (n % 0x40)
)
elseif n < 0x10000 then
+ -- 1110bbbb : 0xE0 : n >> 12
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
return char(
0xE0 + floor(n/0x1000),
0x80 + (floor(n/0x40) % 0x40),
0x80 + (n % 0x40)
)
- elseif n < 0x40000 then
+ elseif n < 0x200000 then
+ -- 11110ccc : 0xF0 : n >> 18
+ -- 10ccbbbb : 0x80 : (n >> 12) & 0x3F
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
+ -- dddd : ccccc - 1
return char(
- 0xF0 + floor(n/0x40000),
- 0x80 + floor(n/0x1000),
+ 0xF0 + floor(n/0x40000),
+ 0x80 + (floor(n/0x1000) % 0x40),
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 "?"
+ return ""
end
end
end
-local unicode = unicode
+if not utf.byte then
+
+ local utf8byte = patterns.utf8byte
+
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+
+end
+
+local utfchar, utfbyte = utf.char, utf.byte
+
+-- As we want to get rid of the (unmaintained) utf library we implement our own
+-- variants (in due time an independent module):
+
+function unicode.filetype(data)
+ return data and lpegmatch(utftype,data) or "unknown"
+end
+
+local toentities = 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
-utf = utf or unicode.utf8
-local concat = table.concat
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
-local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-local type = type
-local utfsplitlines = string.utfsplitlines
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+-- actually one of them is already utf ... sort of useless this one
+
+-- function utf.char(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
+--
+-- merge into:
+
+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
+
+local validatedutf = Cs (
+ (
+ patterns.utf8one
+ + patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ + P(1) / "�"
+ )^0
+)
+
+patterns.validatedutf = validatedutf
+
+function string.validutf(str)
+ return lpegmatch(validatedutf,str)
+end
+
+
+utf.length = string.utflength
+utf.split = string.utfsplit
+utf.splitines = string.utfsplitlines
+utf.valid = string.validutf
+
+if not utf.len then
+ utf.len = utf.length
+end
+
+-- a replacement for simple gsubs:
+
+local utf8char = patterns.utf8char
+
+function utf.remapper(mapping)
+ local pattern = Cs((utf8char/mapping)^0)
+ return function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end, pattern
+end
+
+-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
+-- print(remap("abcd 1234 abcd"))
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
@@ -4027,11 +4616,22 @@ local function big(c)
end
end
+-- function unicode.utf8_to_utf16(str,littleendian)
+-- if littleendian then
+-- return char(255,254) .. utfgsub(str,".",little)
+-- else
+-- return char(254,255) .. utfgsub(str,".",big)
+-- end
+-- end
+
+local _, l_remap = utf.remapper(little)
+local _, b_remap = utf.remapper(big)
+
function unicode.utf8_to_utf16(str,littleendian)
if littleendian then
- return char(255,254) .. utfgsub(str,".",little)
+ return char(255,254) .. lpegmatch(l_remap,str)
else
- return char(254,255) .. utfgsub(str,".",big)
+ return char(254,255) .. lpegmatch(b_remap,str)
end
end
@@ -4052,84 +4652,12 @@ function unicode.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
+--
-local lpegmatch = lpeg.match
-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)
-
--- actually one of them is already utf ... sort of useless this one
-
-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
-
-local validatedutf = Cs (
- (
- patterns.utf8one
- + patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- + P(1) / "�"
- )^0
-)
-
-patterns.validatedutf = validatedutf
+local pattern = Ct(C(patterns.utf8char)^0)
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
+function utf.totable(str)
+ return lpegmatch(pattern,str)
end
@@ -4189,10 +4717,11 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch, rep = string.format, string.gmatch, string.rep
+local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub
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
+local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring
+local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -4346,6 +4875,121 @@ function tables.encapsulate(core,capsule,protect)
end
end
+local function serialize(t,r,outer) -- no mixes
+ r[#r+1] = "{"
+ local n = #t
+ if n > 0 then
+ for i=1,n do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("%q,",v)
+ elseif tv == "number" then
+ r[#r+1] = format("%s,",v)
+ elseif tv == "table" then
+ serialize(v,r)
+ elseif tv == "boolean" then
+ r[#r+1] = format("%s,",tostring(v))
+ end
+ end
+ else
+ for k, v in next, t do
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("[%q]=%q,",k,v)
+ elseif tv == "number" then
+ r[#r+1] = format("[%q]=%s,",k,v)
+ elseif tv == "table" then
+ r[#r+1] = format("[%q]=",k)
+ serialize(v,r)
+ elseif tv == "boolean" then
+ r[#r+1] = format("[%q]=%s,",k,tostring(v))
+ end
+ end
+ end
+ if outer then
+ r[#r+1] = "}"
+ else
+ r[#r+1] = "},"
+ end
+ return r
+end
+
+function table.fastserialize(t,prefix)
+ return concat(serialize(t,{ prefix or "return" },true))
+end
+
+function table.deserialize(str)
+ if not str or str == "" then
+ return
+ end
+ local code = loadstring(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
+end
+
+-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
+
+function table.load(filename)
+ if filename then
+ local t = io.loaddata(filename)
+ if t and t ~= "" then
+ t = loadstring(t)
+ if type(t) == "function" then
+ t = t()
+ if type(t) == "table" then
+ return t
+ end
+ end
+ end
+ end
+end
+
+local function slowdrop(t)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = format("%s=%q",k,v)
+ end
+ r[i] = format(" {%s},\n",concat(l))
+ end
+ return format("return {\n%s}",concat(r))
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ for i=1,#t do
+ local ti = t[i]
+ r[#r+1] = " {"
+ for k, v in next, ti do
+ r[#r+1] = format("%s=%q",k,v)
+ end
+ r[#r+1] = "},\n"
+ end
+ r[#r+1] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow)
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
+
end -- of closure
@@ -4520,11 +5164,10 @@ local concat = table.concat
local type, next = type, next
utilities = utilities or {}
-utilities.merger = utilities.merger or { } -- maybe mergers
+local merger = utilities.merger or { }
+utilities.merger = merger
utilities.report = logs and logs.reporter("system") or print
-local merger = utilities.merger
-
merger.strip_comment = true
local m_begin_merge = "begin library merge"
@@ -4570,9 +5213,11 @@ end
local function self_save(name, data)
if data ~= "" then
if merger.strip_comment then
- -- saves some 20K
local n = #data
+ -- saves some 20K .. scite comments
data = gsub(data,"%-%-~[^\n\r]*[\r\n]","")
+ -- saves some 20K .. ldx comments
+ data = gsub(data,"%-%-%[%[ldx%-%-.-%-%-ldx%]%]%-%-","")
utilities.report("merge: %s bytes of comment stripped, %s bytes of code left",n-#data,#data)
end
io.savedata(name,data)
@@ -4653,36 +5298,208 @@ if not modules then modules = { } end modules ['util-lua'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment = "the strip code is written by Peter Cawley",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-utilities = utilities or {}
-utilities.lua = utilities.lua or { }
-utilities.report = logs and logs.reporter("system") or print
+local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
+local loadstring, loadfile, type = loadstring, loadfile, type
-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)
+utilities = utilities or {}
+utilities.lua = utilities.lua or { }
+local luautilities = utilities.lua
+
+utilities.report = logs and logs.reporter("system") or print -- can be overloaded later
+
+local tracestripping = false
+local forcestupidcompile = true -- use internal bytecode compiler
+luautilities.stripcode = true -- support stripping when asked for
+luautilities.alwaysstripcode = false -- saves 1 meg on 7 meg compressed format file (2012.08.12)
+luautilities.nofstrippedchunks = 0
+luautilities.nofstrippedbytes = 0
+
+-- The next function was posted by Peter Cawley on the lua list and strips line
+-- number information etc. from the bytecode data blob. We only apply this trick
+-- when we store data tables. Stripping makes the compressed format file about
+-- 1MB smaller (and uncompressed we save at least 6MB).
+--
+-- You can consider this feature an experiment, so it might disappear. There is
+-- no noticeable gain in runtime although the memory footprint should be somewhat
+-- smaller (and the file system has a bit less to deal with).
+--
+-- Begin of borrowed code ... works for Lua 5.1 which LuaTeX currently uses ...
+
+local function strip_code_pc(dump,name)
+ local before = #dump
+ local version, format, endian, int, size, ins, num = byte(dump,5,11)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
end
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
+ end
+ end
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ end
+ end
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. sub(dump,dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(sub(dump,offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
+ end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. rep("\0", int * 3)
+ return stripped, offset
+ end
+ dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
+ local after = #dump
+ local delta = before-after
+ if tracestripping then
+ utilities.report("stripped bytecode: %s, before %s, after %s, delta %s",name or "unknown",before,after,delta)
+ end
+ luautilities.nofstrippedchunks = luautilities.nofstrippedchunks + 1
+ luautilities.nofstrippedbytes = luautilities.nofstrippedbytes + delta
+ return dump, delta
+end
+
+-- ... end of borrowed code.
+
+local function strippedbytecode(code,forcestrip,name)
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ return strip_code_pc(code,name)
+ else
+ return code, 0
end
end
-function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
+luautilities.stripbytecode = strip_code_pc
+luautilities.strippedbytecode = strippedbytecode
+
+local function fatalerror(name)
+ utilities.report(format("fatal error in %q",name or "unknown"))
+end
+
+-- quite subtle ... doing this wrong incidentally can give more bytes
+
+
+function luautilities.loadedluacode(fullname,forcestrip,name)
+ -- quite subtle ... doing this wrong incidentally can give more bytes
+ name = name or fullname
+ local code = loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip) == "function" then
+ forcestrip = forcestrip(fullname)
+ end
+ if forcestrip then
+ local code, n = strip_code_pc(dump(code,name))
+ return loadstring(code), n
+ elseif luautilities.alwaysstripcode then
+ return loadstring(strip_code_pc(dump(code),name))
+ else
+ return code, 0
+ end
+ elseif luautilities.alwaysstripcode then
+ return loadstring(strip_code_pc(dump(code),name))
+ else
+ return code, 0
+ end
+end
+
+function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
+ local n = 0
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ code = loadstring(code)
+ if not code then
+ fatalerror(name)
+ end
+ code, n = strip_code_pc(dump(code),name)
+ end
+ return loadstring(code), n
+end
+
+local function stupidcompile(luafile,lucfile,strip)
+ local code = io.loaddata(luafile)
+ local n = 0
+ if code and code ~= "" then
+ code = loadstring(code)
+ if not code then
+ fatalerror()
+ end
+ code = dump(code)
+ if strip then
+ code, n = strippedbytecode(code,true,luafile) -- last one is reported
+ end
+ if code and code ~= "" then
+ io.savedata(lucfile,code)
+ end
+ end
+ return n
+end
+
+local luac_normal = "texluac -o %q %q"
+local luac_strip = "texluac -s -o %q %q"
+
+function luautilities.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)
+ local done = false
if strip ~= false then
- command = "-s " .. command
+ strip = true
+ end
+ if forcestupidcompile then
+ fallback = true
+ elseif strip then
+ done = os.spawn(format(luac_strip, lucfile,luafile)) == 0
+ else
+ done = os.spawn(format(luac_normal,lucfile,luafile)) == 0
end
- 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
+ local n = stupidcompile(luafile,lucfile,strip)
+ if n > 0 then
+ utilities.report("lua: %s dumped into %s (%i bytes stripped)",luafile,lucfile,n)
+ else
+ utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile)
+ end
+ cleanup = false -- better see how bad it is
end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
@@ -4697,7 +5514,6 @@ end
-
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -4710,8 +5526,10 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-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 lpeg, table, string = lpeg, table, string
+
+local P, R, V, S, C, Ct, Cs, Carg, Cc = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
@@ -4723,29 +5541,39 @@ parsers.patterns = parsers.patterns or { }
local setmetatableindex = table.setmetatableindex
local sortedhash = table.sortedhash
+-- we share some patterns
+
+local space = P(' ')
+local equal = P("=")
+local comma = P(",")
+local lbrace = P("{")
+local rbrace = P("}")
+local period = S(".")
+local punctuation = S(".,:;")
+local spacer = patterns.spacer
+local whitespace = patterns.whitespace
+local newline = patterns.newline
+local anything = patterns.anything
+local endofstring = patterns.endofstring
+
-- we could use a Cf Cg construct
local escape, left, right = P("\\"), P('{'), P('}')
-lpeg.patterns.balanced = P {
+patterns.balanced = P {
[1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0,
[2] = left * V(1) * right
}
-local space = P(' ')
-local equal = P("=")
-local comma = P(",")
-local lbrace = P("{")
-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
+local content = (1-endofstring)^0
-lpeg.patterns.nested = nested -- no capture
-lpeg.patterns.argument = argument -- argument after e.g. =
-lpeg.patterns.content = content -- rest after e.g =
+patterns.nested = nested -- no capture
+patterns.argument = argument -- argument after e.g. =
+patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4764,10 +5592,6 @@ local function set(key,value)
hash[key] = value
end
-local function set(key,value)
- hash[key] = value
-end
-
local pattern_a_s = (pattern_a/set)^1
local pattern_b_s = (pattern_b/set)^1
local pattern_c_s = (pattern_c/set)^1
@@ -4818,7 +5642,7 @@ end
local separator = comma * space^0
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-local pattern = Ct(value*(separator*value)^0)
+local pattern = spaces * Ct(value*(separator*value)^0)
-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
@@ -4942,6 +5766,37 @@ function parsers.listitem(str)
return gmatch(str,"[^, ]+")
end
+--
+local digit = R("09")
+
+local pattern = Cs { "start",
+ start = V("one") + V("two") + V("three"),
+ rest = (Cc(",") * V("thousand"))^0 * (P(".") + endofstring) * anything^0,
+ thousand = digit * digit * digit,
+ one = digit * V("rest"),
+ two = digit * digit * V("rest"),
+ three = V("thousand") * V("rest"),
+}
+
+patterns.splitthousands = pattern -- maybe better in the parsers namespace ?
+
+function parsers.splitthousands(str)
+ return lpegmatch(pattern,str) or str
+end
+
+-- print(parsers.splitthousands("11111111111.11"))
+
+local optionalwhitespace = whitespace^0
+
+patterns.words = Ct((Cs((1-punctuation-whitespace)^1) + anything)^1)
+patterns.sentences = Ct((optionalwhitespace * Cs((1-period)^0 * period))^1)
+patterns.paragraphs = Ct((optionalwhitespace * Cs((whitespace^1*endofstring/"" + 1 - (spacer^0*newline*newline))^1))^1)
+
+-- local str = " Word1 word2. \n Word3 word4. \n\n Word5 word6.\n "
+-- inspect(lpegmatch(patterns.paragraphs,str))
+-- inspect(lpegmatch(patterns.sentences,str))
+-- inspect(lpegmatch(patterns.words,str))
+
end -- of closure
@@ -5043,7 +5898,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util.deb'] = {
+if not modules then modules = { } end modules ['util-deb'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -5155,6 +6010,7 @@ function inspect(i) -- global function
else
print(tostring(i))
end
+ return i -- so that we can inline the inspect
end
-- from the lua book:
@@ -5194,7 +6050,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
-local write_nl = texio.write_nl
+local write_nl = texio and texio.write_nl or print
statistics = statistics or { }
local statistics = statistics
@@ -5277,7 +6133,7 @@ statistics.elapsedtime = elapsedtime
statistics.elapsedindeed = elapsedindeed
statistics.elapsedseconds = elapsedseconds
--- general function
+-- general function .. we might split this module
function statistics.register(tag,fnc)
if statistics.enable and type(fnc) == "function" then
@@ -5387,6 +6243,8 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
license = "see context related readme files"
}
+-- maybe this should be util-set.lua
+
local type, next, tostring = type, next, tostring
local concat = table.concat
local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
@@ -5586,7 +6444,7 @@ function setters.show(t)
local value, default, modules = functions.value, functions.default, #functions
value = value == nil and "unset" or tostring(value)
default = default == nil and "unset" or tostring(default)
- t.report("%-30s modules: %2i default: %6s value: %6s",name,modules,default,value)
+ t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value)
end
end
t.report()
@@ -5678,17 +6536,31 @@ end)
-- experiment
-local flags = environment and environment.engineflags
+if environment then
-if flags then
- if trackers and flags.trackers then
- setters.initialize("flags","trackers", settings_to_hash(flags.trackers))
- -- t_enable(flags.trackers)
- end
- if directives and flags.directives then
- setters.initialize("flags","directives", settings_to_hash(flags.directives))
- -- d_enable(flags.directives)
+ -- The engineflags are known earlier than environment.arguments but maybe we
+ -- need to handle them both as the later are parsed differently. The c: prefix
+ -- is used by mtx-context to isolate the flags from those that concern luatex.
+
+ local engineflags = environment.engineflags
+
+ if engineflags then
+ if trackers then
+ local list = engineflags["c:trackers"] or engineflags["trackers"]
+ if type(list) == "string" then
+ setters.initialize("flags","trackers",settings_to_hash(list))
+ -- t_enable(list)
+ end
+ end
+ if directives then
+ local list = engineflags["c:directives"] or engineflags["directives"]
+ if type(list) == "string" then
+ setters.initialize("flags","directives", settings_to_hash(list))
+ -- d_enable(list)
+ end
+ end
end
+
end
-- here
@@ -5741,10 +6613,7 @@ local next, type = next, type
local setmetatableindex = table.setmetatableindex
---[[ldx--
-<p>This is a prelude to a more extensive logging module. We no longer
-provide <l n='xml'/> based logging a sparsing is relatively easy anyway.</p>
---ldx]]--
+
logs = logs or { }
local logs = logs
@@ -6560,7 +7429,8 @@ local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
local unquoted, quoted = string.unquoted, string.quoted
-local concat = table.concat
+local concat, insert, remove = table.concat, table.insert, table.remove
+local loadedluacode = utilities.lua.loadedluacode
-- precautions
@@ -6578,8 +7448,28 @@ if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaon
for k=3,#arg do
arg[k-2] = arg[k]
end
- arg[#arg] = nil -- last
- arg[#arg] = nil -- pre-last
+ remove(arg) -- last
+ remove(arg) -- pre-last
+end
+
+-- This is an ugly hack but it permits symlinking a script (say 'context') to 'mtxrun' as in:
+--
+-- ln -s /opt/minimals/tex/texmf-linux-64/bin/mtxrun context
+--
+-- The special mapping hack is needed because 'luatools' boils down to 'mtxrun --script base'
+-- but it's unlikely that there will be more of this
+
+do
+
+ local originalzero = file.basename(arg[0])
+ local specialmapping = { luatools == "base" }
+
+ if originalzero ~= "mtxrun" and originalzero ~= "mtxrun.lua" then
+ arg[0] = specialmapping[originalzero] or originalzero
+ insert(arg,0,"--script")
+ insert(arg,0,"mtxrun")
+ end
+
end
-- environment
@@ -6619,6 +7509,8 @@ local mt = {
setmetatable(environment,mt)
+-- context specific arguments (in order not to confuse the engine)
+
function environment.initializearguments(arg)
local arguments, files = { }, { }
environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
@@ -6627,10 +7519,12 @@ function environment.initializearguments(arg)
if index > 0 then
local flag, value = match(argument,"^%-+(.-)=(.-)$")
if flag then
+ flag = gsub(flag,"^c:","")
arguments[flag] = unquoted(value or "")
else
flag = match(argument,"^%-+(.+)")
if flag then
+ flag = gsub(flag,"^c:","")
arguments[flag] = true
else
files[#files+1] = argument
@@ -6650,7 +7544,7 @@ end
-- tricky: too many hits when we support partials unless we add
-- a registration of arguments so from now on we have 'partial'
-function environment.argument(name,partial)
+function environment.getargument(name,partial)
local arguments, sortedflags = environment.arguments, environment.sortedflags
if arguments[name] then
return arguments[name]
@@ -6673,6 +7567,8 @@ function environment.argument(name,partial)
return nil
end
+environment.argument = environment.getargument
+
function environment.splitarguments(separator) -- rather special, cut-off before separator
local done, before, after = false, { }, { }
local originalarguments = environment.originalarguments
@@ -6758,7 +7654,7 @@ function environment.texfile(filename)
return resolvers.findfile(filename,'tex')
end
-function environment.luafile(filename)
+function environment.luafile(filename) -- needs checking
local resolved = resolvers.findfile(filename,'tex') or ""
if resolved ~= "" then
return resolved
@@ -6770,13 +7666,16 @@ function environment.luafile(filename)
return resolvers.findfile(filename,'luatexlibs') or ""
end
-environment.loadedluacode = loadfile -- can be overloaded
+local function checkstrip(filename)
+ local modu = modules[file.nameonly(filename)]
+ return modu and modu.dataonly
+end
function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format
filename = file.replacesuffix(filename, "lua")
local fullname = environment.luafile(filename)
if fullname and fullname ~= "" then
- local data = environment.loadedluacode(fullname)
+ local data = loadedluacode(fullname,checkstrip,filename)
if trace_locating then
report_lua("loading file %s%s", fullname, not data and " failed" or "")
elseif not silent then
@@ -6874,21 +7773,7 @@ local trace_entities = false trackers.register("xml.entities", function(v) trac
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
---[[ldx--
-<p>The parser used here is inspired by the variant discussed in the lua book, but
-handles comment and processing instructions, has a different structure, provides
-parent access; a first version used different trickery but was less optimized to we
-went this route. First we had a find based parser, now we have an <l n='lpeg'/> based one.
-The find based parser can be found in l-xml-edu.lua along with other older code.</p>
-
-<p>Beware, the interface may change. For instance at, ns, tg, dt may get more
-verbose names. Once the code is stable we will also remove some tracing and
-optimize the code.</p>
-<p>I might even decide to reimplement the parser using the latest <l n='lpeg'/> trickery
-as the current variant was written when <l n='lpeg'/> showed up and it's easier now to
-build tables in one go.</p>
---ldx]]--
xml = xml or { }
local xml = xml
@@ -6898,46 +7783,25 @@ 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, utffind, utfgsub = utf.char, utf.find, utf.gsub
+local utfchar = utf.char
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
---[[ldx--
-<p>First a hack to enable namespace resolving. A namespace is characterized by
-a <l n='url'/>. The following function associates a namespace prefix with a
-pattern. We use <l n='lpeg'/>, which in this case is more than twice as fast as a
-find based solution where we loop over an array of patterns. Less code and
-much cleaner.</p>
---ldx]]--
+
xml.xmlns = xml.xmlns or { }
local check = P(false)
local parse = check
---[[ldx--
-<p>The next function associates a namespace prefix with an <l n='url'/>. This
-normally happens independent of parsing.</p>
-<typing>
-xml.registerns("mml","mathml")
-</typing>
---ldx]]--
function xml.registerns(namespace, pattern) -- pattern can be an lpeg
check = check + C(P(lower(pattern))) / namespace
parse = P { P(check) + 1 * V(1) }
end
---[[ldx--
-<p>The next function also registers a namespace, but this time we map a
-given namespace prefix onto a registered one, using the given
-<l n='url'/>. This used for attributes like <t>xmlns:m</t>.</p>
-<typing>
-xml.checkns("m","http://www.w3.org/mathml")
-</typing>
---ldx]]--
function xml.checkns(namespace,url)
local ns = lpegmatch(parse,lower(url))
@@ -6946,66 +7810,15 @@ function xml.checkns(namespace,url)
end
end
---[[ldx--
-<p>Next we provide a way to turn an <l n='url'/> into a registered
-namespace. This used for the <t>xmlns</t> attribute.</p>
-
-<typing>
-resolvedns = xml.resolvens("http://www.w3.org/mathml")
-</typing>
-This returns <t>mml</t>.
---ldx]]--
function xml.resolvens(url)
return lpegmatch(parse,lower(url)) or ""
end
---[[ldx--
-<p>A namespace in an element can be remapped onto the registered
-one efficiently by using the <t>xml.xmlns</t> table.</p>
---ldx]]--
-
---[[ldx--
-<p>This version uses <l n='lpeg'/>. We follow the same approach as before, stack and top and
-such. This version is about twice as fast which is mostly due to the fact that
-we don't have to prepare the stream for cdata, doctype etc etc. This variant is
-is dedicated to Luigi Scarso, who challenged me with 40 megabyte <l n='xml'/> files that
-took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
-the <l n='lpeg'/> implementation we got that down to less 7.3 seconds. Loading the 14
-<l n='context'/> interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.</p>
-
-<p>Next comes the parser. The rather messy doctype definition comes in many
-disguises so it is no surprice that later on have to dedicate quite some
-<l n='lpeg'/> code to it.</p>
-
-<typing>
-<!DOCTYPE Something PUBLIC "... ..." "..." [ ... ] >
-<!DOCTYPE Something PUBLIC "... ..." "..." >
-<!DOCTYPE Something SYSTEM "... ..." [ ... ] >
-<!DOCTYPE Something SYSTEM "... ..." >
-<!DOCTYPE Something [ ... ] >
-<!DOCTYPE Something >
-</typing>
-
-<p>The code may look a bit complex but this is mostly due to the fact that we
-resolve namespaces and attach metatables. There is only one public function:</p>
-
-<typing>
-local x = xml.convert(somestring)
-</typing>
-
-<p>An optional second boolean argument tells this function not to create a root
-element.</p>
-
-<p>Valid entities are:</p>
-
-<typing>
-<!ENTITY xxxx SYSTEM "yyyy" NDATA zzzz>
-<!ENTITY xxxx PUBLIC "yyyy" >
-<!ENTITY xxxx "yyyy" >
-</typing>
---ldx]]--
+
+
+
-- not just one big nested table capture (lpeg overflow)
@@ -7220,15 +8033,7 @@ 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 escaped = utf.remapper(privates_u)
local function unescaped(s)
local p = privates_n[s]
@@ -7243,13 +8048,7 @@ local function unescaped(s)
return p
end
-local function unprivatized(s,resolve)
- if s == "" then
- return ""
- else
- return (utfgsub(s,".",privates_p))
- end
-end
+local unprivatized = utf.remapper(privates_p)
xml.privatetoken = unescaped
xml.unprivatized = unprivatized
@@ -7589,7 +8388,12 @@ local function _xmlconvert_(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler(format("load error: %s",errorstr))
+ local currentresource = settings.currentresource
+ if currentresource and currentresource ~= "" then
+ xml.errorhandler(format("load error in [%s]: %s",currentresource,errorstr))
+ else
+ xml.errorhandler(format("load error: %s",errorstr))
+ end
end
end
else
@@ -7634,7 +8438,7 @@ function xmlconvert(data,settings)
if ok then
return result
else
- return _xmlconvert_("")
+ return _xmlconvert_("",settings)
end
end
@@ -7655,10 +8459,7 @@ function xml.inheritedconvert(data,xmldata) -- xmldata is parent
return xc
end
---[[ldx--
-<p>Packaging data in an xml like table is done with the following
-function. Maybe it will go away (when not used).</p>
---ldx]]--
+
function xml.is_valid(root)
return root and root.dt and root.dt[1] and type(root.dt[1]) == "table" and not root.dt[1].er
@@ -7677,11 +8478,7 @@ end
xml.errorhandler = report_xml
---[[ldx--
-<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
-the whole file first. The function accepts a string representing
-a filename or a file handle.</p>
---ldx]]--
+
function xml.load(filename,settings)
local data = ""
@@ -7695,13 +8492,17 @@ function xml.load(filename,settings)
elseif filename then -- filehandle
data = filename:read("*all")
end
- return xmlconvert(data,settings)
+ if settings then
+ settings.currentresource = filename
+ local result = xmlconvert(data,settings)
+ settings.currentresource = nil
+ return result
+ else
+ return xmlconvert(data,{ currentresource = filename })
+ end
end
---[[ldx--
-<p>When we inject new elements, we need to convert strings to
-valid trees, which is what the next function does.</p>
---ldx]]--
+
local no_root = { no_root = true }
@@ -7714,11 +8515,7 @@ function xml.toxml(data)
end
end
---[[ldx--
-<p>For copying a tree we use a dedicated function instead of the
-generic table copier. Since we know what we're dealing with we
-can speed up things a bit. The second argument is not to be used!</p>
---ldx]]--
+
local function copy(old,tables)
if old then
@@ -7742,13 +8539,7 @@ end
xml.copy = copy
---[[ldx--
-<p>In <l n='context'/> serializing the tree or parts of the tree is a major
-actitivity which is why the following function is pretty optimized resulting
-in a few more lines of code than needed. The variant that uses the formatting
-function for all components is about 15% slower than the concatinating
-alternative.</p>
---ldx]]--
+
-- todo: add <?xml version='1.0' standalone='yes'?> when not present
@@ -7761,15 +8552,12 @@ function xml.checkbom(root) -- can be made faster
return
end
end
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 1, { special = true, ns = "", tg = "@pi@", dt = { "xml version='1.0' standalone='yes'" } } )
insert(dt, 2, "\n" )
end
end
---[[ldx--
-<p>At the cost of some 25% runtime overhead you can first convert the tree to a string
-and then handle the lot.</p>
---ldx]]--
+
-- new experimental reorganized serialize
@@ -7962,21 +8750,7 @@ newhandlers {
}
}
---[[ldx--
-<p>How you deal with saving data depends on your preferences. For a 40 MB database
-file the timing on a 2.3 Core Duo are as follows (time in seconds):</p>
-
-<lines>
-1.3 : load data from file to string
-6.1 : convert string into tree
-5.3 : saving in file using xmlsave
-6.8 : converting to string using xml.tostring
-3.6 : saving converted string in file
-</lines>
-<p>Beware, these were timing with the old routine but measurements will not be that
-much different I guess.</p>
---ldx]]--
-- maybe this will move to lxml-xml
@@ -8054,10 +8828,7 @@ xml.newhandlers = newhandlers
xml.serialize = serialize
xml.tostring = xmltostring
---[[ldx--
-<p>The next function operated on the content only and needs a handle function
-that accepts a string.</p>
---ldx]]--
+
local function xmlstring(e,handle)
if not handle or (e.special and e.tg ~= "@rt@") then
@@ -8076,9 +8847,7 @@ end
xml.string = xmlstring
---[[ldx--
-<p>A few helpers:</p>
---ldx]]--
+
function xml.settings(e)
@@ -8122,11 +8891,7 @@ function xml.name(root)
end
end
---[[ldx--
-<p>The next helper erases an element but keeps the table as it is,
-and since empty strings are not serialized (effectively) it does
-not harm. Copying the table would take more time. Usage:</p>
---ldx]]--
+
function xml.erase(dt,k)
if dt then
@@ -8138,13 +8903,7 @@ function xml.erase(dt,k)
end
end
---[[ldx--
-<p>The next helper assigns a tree (or string). Usage:</p>
-<typing>
-dt[k] = xml.assign(root) or xml.assign(dt,k,root)
-</typing>
---ldx]]--
function xml.assign(dt,k,root)
if dt and k then
@@ -8157,20 +8916,14 @@ end
-- the following helpers may move
---[[ldx--
-<p>The next helper assigns a tree (or string). Usage:</p>
-<typing>
-xml.tocdata(e)
-xml.tocdata(e,"error")
-</typing>
---ldx]]--
+
function xml.tocdata(e,wrapper) -- a few more in the aux module
local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
- local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e }
+ local t = { special = true, ns = "", tg = "@cd@", at = { }, rn = "", dt = { whatever }, __p__ = e }
setmetatable(t,getmetatable(e))
e.dt = { t }
end
@@ -8225,7 +8978,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['lxml-pth'] = {
+if not modules then modules = { } end modules ['lxml-lpt'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -8246,28 +8999,9 @@ local setmetatableindex = table.setmetatableindex
-- beware, this is not xpath ... e.g. position is different (currently) and
-- we have reverse-sibling as reversed preceding sibling
---[[ldx--
-<p>This module can be used stand alone but also inside <l n='mkiv'/> in
-which case it hooks into the tracker code. Therefore we provide a few
-functions that set the tracers. Here we overload a previously defined
-function.</p>
-<p>If I can get in the mood I will make a variant that is XSLT compliant
-but I wonder if it makes sense.</P>
---ldx]]--
-
---[[ldx--
-<p>Expecially the lpath code is experimental, we will support some of xpath, but
-only things that make sense for us; as compensation it is possible to hook in your
-own functions. Apart from preprocessing content for <l n='context'/> we also need
-this module for process management, like handling <l n='ctx'/> and <l n='rlx'/>
-files.</p>
-
-<typing>
-a/b/c /*/c
-a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
-a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
-</typing>
---ldx]]--
+
+
+
local trace_lpath = false if trackers then trackers.register("xml.path", function(v) trace_lpath = v end) end
local trace_lparse = false if trackers then trackers.register("xml.parse", function(v) trace_lparse = v end) end
@@ -8275,11 +9009,7 @@ local trace_lprofile = false if trackers then trackers.register("xml.profile",
local report_lpath = logs.reporter("xml","lpath")
---[[ldx--
-<p>We've now arrived at an interesting part: accessing the tree using a subset
-of <l n='xpath'/> and since we're not compatible we call it <l n='lpath'/>. We
-will explain more about its usage in other documents.</p>
---ldx]]--
+
local xml = xml
@@ -8731,14 +9461,23 @@ local lp_builtin = P (
-- for the moment we keep namespaces with attributes
local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])")
-local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end)
-local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end)
+
+-- lp_fastpos_p = (P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end
+-- lp_fastpos_n = (P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end
+
+lp_fastpos_p = P("+")^0 * R("09")^1 * P(-1) / "l==%0"
+lp_fastpos_n = P("-") * R("09")^1 * P(-1) / "(%0<0 and (#list+%0==l))"
+
local lp_fastpos = lp_fastpos_n + lp_fastpos_p
+
local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
-local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
- return t .. "("
-end
+-- local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
+-- return t .. "("
+-- end
+
+-- local lp_lua_function = (R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / "%0("
+local lp_lua_function = Cs((R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(")) / "%0"
local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
if expressions[t] then
@@ -9254,9 +9993,7 @@ end
xml.applylpath = applylpath -- takes a table as first argment, which is what xml.filter will do
---[[ldx--
-<p>This is the main filter function. It returns whatever is asked for.</p>
---ldx]]--
+
function xml.filter(root,pattern) -- no longer funny attribute handling here
return applylpath(root,pattern)
@@ -9354,12 +10091,12 @@ xml.selection = selection -- new method, simple handle
-- generic function finalizer (independant namespace)
-local function dofunction(collected,fnc)
+local function dofunction(collected,fnc,...)
if collected then
local f = functions[fnc]
if f then
for c=1,#collected do
- f(collected[c])
+ f(collected[c],...)
end
else
report_lpath("unknown function '%s'",fnc)
@@ -9460,21 +10197,7 @@ expressions.tag = function(e,n) -- only tg
end
end
---[[ldx--
-<p>Often using an iterators looks nicer in the code than passing handler
-functions. The <l n='lua'/> book describes how to use coroutines for that
-purpose (<url href='http://www.lua.org/pil/9.3.html'/>). This permits
-code like:</p>
-<typing>
-for r, d, k in xml.elements(xml.load('text.xml'),"title") do
- print(d[k]) -- old method
-end
-for e in xml.collected(xml.load('text.xml'),"title") do
- print(e) -- new one
-end
-</typing>
---ldx]]--
local wrap, yield = coroutine.wrap, coroutine.yield
@@ -9515,6 +10238,32 @@ function xml.inspect(collection,pattern)
end
end
+-- texy (see xfdf):
+
+local function split(e)
+ local dt = e.dt
+ if dt then
+ for i=1,#dt do
+ local dti = dt[i]
+ if type(dti) == "string" then
+ dti = gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1")
+ dti = gsub(dti,"[\n\r]+","\n\n")
+ dt[i] = dti
+ else
+ split(dti)
+ end
+ end
+ end
+ return e
+end
+
+function xml.finalizers.paragraphs(c)
+ for i=1,#c do
+ split(c[i])
+ end
+ return c
+end
+
end -- of closure
@@ -9539,13 +10288,7 @@ local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, l
lpegpatterns.xml = lpegpatterns.xml or { }
local xmlpatterns = lpegpatterns.xml
---[[ldx--
-<p>The following helper functions best belong to the <t>lxml-ini</t>
-module. Some are here because we need then in the <t>mk</t>
-document and other manuals, others came up when playing with
-this module. Since this module is also used in <l n='mtxrun'/> we've
-put them here instead of loading mode modules there then needed.</p>
---ldx]]--
+
local function xmlgsub(t,old,new) -- will be replaced
local dt = t.dt
@@ -9731,9 +10474,7 @@ function xml.processattributes(root,pattern,handle)
return collected
end
---[[ldx--
-<p>The following functions collect elements and texts.</p>
---ldx]]--
+
-- are these still needed -> lxml-cmp.lua
@@ -9772,9 +10513,7 @@ function xml.collect_tags(root, pattern, nonamespace)
end
end
---[[ldx--
-<p>We've now arrived at the functions that manipulate the tree.</p>
---ldx]]--
+
local no_root = { no_root = true }
@@ -10160,9 +10899,7 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
end
---[[ldx--
-<p>Helper (for q2p).</p>
---ldx]]--
+
function xml.cdatatotext(e)
local dt = e.dt
@@ -10259,9 +10996,7 @@ end
-- xml.addentitiesdoctype(x,"hexadecimal")
-- print(x)
---[[ldx--
-<p>Here are a few synonyms.</p>
---ldx]]--
+
xml.all = xml.each
xml.insert = xml.insertafter
@@ -10852,7 +11587,7 @@ local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string
local concat = table.concat
local next, type = next, type
-local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
+local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
@@ -11202,12 +11937,14 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
for s in gmatch(str,"[^,]+") do
s = validate(s)
if s then
- n = n + 1 ; t[n] = s
+ n = n + 1
+ t[n] = s
end
end
else
for s in gmatch(str,"[^,]+") do
- n = n + 1 ; t[n] = s
+ n = n + 1
+ t[n] = s
end
end
if trace_expansions then
@@ -11221,7 +11958,7 @@ end
-- We could make the previous one public.
local function validate(s)
- s = collapsepath(s) -- already keeps the //
+ s = collapsepath(s) -- already keeps the trailing / and //
return s ~= "" and not find(s,"^!*unset/*$") and s
end
@@ -11559,7 +12296,7 @@ local resolvers = resolvers
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
-local fileextname = file.extname
+local suffixonly = file.suffixonly
local formats = allocate()
local suffixes = allocate()
@@ -11814,7 +12551,7 @@ function resolvers.formatofvariable(str)
end
function resolvers.formatofsuffix(str) -- of file
- return suffixmap[fileextname(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
+ return suffixmap[suffixonly(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
end
function resolvers.variableofformat(str)
@@ -11826,7 +12563,7 @@ function resolvers.variableofformatorsuffix(str)
if v then
return v
end
- v = suffixmap[fileextname(str)]
+ v = suffixmap[suffixonly(str)]
if v then
return formats[v]
end
@@ -11847,21 +12584,7 @@ if not modules then modules = { } end modules ['data-tmp'] = {
license = "see context related readme files"
}
---[[ldx--
-<p>This module deals with caching data. It sets up the paths and
-implements loaders and savers for tables. Best is to set the
-following variable. When not set, the usual paths will be
-checked. Personally I prefer the (users) temporary path.</p>
-
-</code>
-TEXMFCACHE=$TMP;$TEMP;$TMPDIR;$TEMPDIR;$HOME;$TEXMFVAR;$VARTEXMF;.
-</code>
-<p>Currently we do no locking when we write files. This is no real
-problem because most caching involves fonts and the chance of them
-being written at the same time is small. We also need to extend
-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
@@ -12396,11 +13119,12 @@ local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local filedirname = file.dirname
local filebasename = file.basename
-local fileextname = file.extname
+local suffixonly = file.suffixonly
local filejoin = file.join
local collapsepath = file.collapsepath
local joinpath = file.joinpath
local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -12424,7 +13148,7 @@ resolvers.cacheversion = '1.0.1'
resolvers.configbanner = ''
resolvers.homedir = environment.homedir
resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" }
-resolvers.luacnfname = 'texmfcnf.lua'
+resolvers.luacnfname = "texmfcnf.lua"
resolvers.luacnfstate = "unknown"
-- The web2c tex binaries as well as kpse have built in paths for the configuration
@@ -12696,7 +13420,7 @@ end
local function identify_configuration_files()
local specification = instance.specification
if #specification == 0 then
- local cnfspec = getenv('TEXMFCNF')
+ local cnfspec = getenv("TEXMFCNF")
if cnfspec == "" then
cnfspec = resolvers.luacnfspec
resolvers.luacnfstate = "default"
@@ -12784,7 +13508,7 @@ local function load_configuration_files()
-- we push the value into the main environment (osenv) so
-- that it takes precedence over the default one and therefore
-- also over following definitions
- resolvers.setenv('TEXMFCNF',cnfspec) -- resolves prefixes
+ resolvers.setenv("TEXMFCNF",cnfspec) -- resolves prefixes
-- we now identify and load the specified configuration files
instance.specification = { }
identify_configuration_files()
@@ -12832,10 +13556,11 @@ end
local function locate_file_databases()
-- todo: cache:// and tree:// (runtime)
- local texmfpaths = resolvers.expandedpathlist('TEXMF')
+ local texmfpaths = resolvers.expandedpathlist("TEXMF")
if #texmfpaths > 0 then
for i=1,#texmfpaths do
local path = collapsepath(texmfpaths[i])
+ path = gsub(path,"/+$","") -- in case $HOME expands to something with a trailing /
local stripped = lpegmatch(inhibitstripper,path) -- the !! thing
if stripped ~= "" then
local runtime = stripped == path
@@ -12964,9 +13689,9 @@ function resolvers.prependhash(type,name,cache)
end
function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash
- local t = resolvers.splitpath(getenv('TEXMF'))
+ local t = resolvers.splitpath(getenv("TEXMF")) -- okay?
insert(t,1,specification)
- local newspec = concat(t,";")
+ local newspec = concat(t,",") -- not ;
if instance.environment["TEXMF"] then
instance.environment["TEXMF"] = newspec
elseif instance.variables["TEXMF"] then
@@ -13041,14 +13766,19 @@ function resolvers.resetextrapath()
end
function resolvers.registerextrapath(paths,subpaths)
+ paths = settings_to_array(paths)
+ subpaths = settings_to_array(subpaths)
local ep = instance.extra_paths or { }
local oldn = #ep
local newn = oldn
- if paths and paths ~= "" then
- if subpaths and subpaths ~= "" then
- for p in gmatch(paths,"[^,]+") do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
+ local nofpaths = #paths
+ local nofsubpaths = #subpaths
+ if nofpaths > 0 then
+ if nofsubpaths > 0 then
+ for i=1,nofpaths do
+ local p = paths[i]
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
local ps = p .. "/" .. s
if not done[ps] then
newn = newn + 1
@@ -13058,7 +13788,8 @@ function resolvers.registerextrapath(paths,subpaths)
end
end
else
- for p in gmatch(paths,"[^,]+") do
+ for i=1,nofpaths do
+ local p = paths[i]
if not done[p] then
newn = newn + 1
ep[newn] = resolvers.cleanpath(p)
@@ -13066,10 +13797,10 @@ function resolvers.registerextrapath(paths,subpaths)
end
end
end
- elseif subpaths and subpaths ~= "" then
+ elseif nofsubpaths > 0 then
for i=1,oldn do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
local ps = ep[i] .. "/" .. s
if not done[ps] then
newn = newn + 1
@@ -13147,18 +13878,21 @@ function resolvers.expandedpathlist(str)
return { }
elseif instance.savelists then
str = lpegmatch(dollarstripper,str)
- if not instance.lists[str] then -- cached
- local lst = made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
- instance.lists[str] = expandedpathfromlist(lst)
- end
- return instance.lists[str]
+ local lists = instance.lists
+ local lst = lists[str]
+ if not lst then
+ local l = made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ lst = expandedpathfromlist(l)
+ lists[str] = lst
+ end
+ return lst
else
local lst = resolvers.splitpath(resolvers.expansion(str))
return made_list(instance,expandedpathfromlist(lst))
end
end
-function resolvers.expandedpathlistfromvariable(str) -- brrr
+function resolvers.expandedpathlistfromvariable(str) -- brrr / could also have cleaner ^!! /$ //
str = lpegmatch(dollarstripper,str)
local tmp = resolvers.variableofformatorsuffix(str)
return resolvers.expandedpathlist(tmp ~= "" and tmp or str)
@@ -13315,7 +14049,7 @@ local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
local collect_instance_files
local function find_analyze(filename,askedformat,allresults)
- local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ local filetype, wantedfiles, ext = '', { }, suffixonly(filename)
-- too tricky as filename can be bla.1.2.3:
--
-- if not suffixmap[ext] then
@@ -13393,7 +14127,7 @@ local function find_qualified(filename,allresults) -- this one will be split too
if trace_detail then
report_resolving("locating qualified file '%s'", filename)
end
- local forcedname, suffix = "", fileextname(filename)
+ local forcedname, suffix = "", suffixonly(filename)
if suffix == "" then -- why
local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
if format_suffixes then
@@ -14063,6 +14797,8 @@ local gsub = string.gsub
local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+local joinpath, basename, dirname = file.join, file.basename, file.dirname
+local getmetatable, rawset, type = getmetatable, rawset, type
-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
@@ -14104,28 +14840,43 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
+ return cleanpath(basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.dirname((fullname ~= "" and fullname) or str))
+ return cleanpath(dirname((fullname ~= "" and fullname) or str))
end
prefixes.selfautoloc = function(str)
- return cleanpath(file.join(getenv('SELFAUTOLOC'),str))
+ return cleanpath(joinpath(getenv('SELFAUTOLOC'),str))
end
prefixes.selfautoparent = function(str)
- return cleanpath(file.join(getenv('SELFAUTOPARENT'),str))
+ return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str))
end
prefixes.selfautodir = function(str)
- return cleanpath(file.join(getenv('SELFAUTODIR'),str))
+ return cleanpath(joinpath(getenv('SELFAUTODIR'),str))
end
prefixes.home = function(str)
- return cleanpath(file.join(getenv('HOME'),str))
+ return cleanpath(joinpath(getenv('HOME'),str))
+end
+
+local function toppath()
+ local pathname = dirname(inputstack[#inputstack] or "")
+ if pathname == "" then
+ return "."
+ else
+ return pathname
+ end
+end
+
+resolvers.toppath = toppath
+
+prefixes.toppath = function(str)
+ return cleanpath(joinpath(toppath(),str))
end
prefixes.env = prefixes.environment
@@ -14161,6 +14912,8 @@ function resolvers.resetresolve(str)
resolved, abstract = { }, { }
end
+-- todo: use an lpeg (see data-lua for !! / stripper)
+
local function resolve(str) -- use schemes, this one is then for the commandline only
if type(str) == "table" then
local t = { }
@@ -14186,7 +14939,7 @@ end
resolvers.resolve = resolve
resolvers.unresolve = unresolve
-if os.uname then
+if type(os.uname) == "function" then
for k, v in next, os.uname() do
if not prefixes[k] then
@@ -14198,11 +14951,17 @@ end
if os.type == "unix" then
+ -- We need to distringuish between a prefix and something else : so we
+ -- have a special repath variant for linux. Also, when a new prefix is
+ -- defined, we need to remake the matcher.
+
local pattern
local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
local colon = P(":")
- local p
for k, v in table.sortedpairs(prefixes) do
if p then
p = P(k) + p
@@ -14211,9 +14970,6 @@ if os.type == "unix" then
end
end
pattern = Cs((p * colon + colon/";" + P(1))^0)
- if t then
- t[k] = v
- end
end
makepattern()
@@ -14424,18 +15180,7 @@ local trace_cache = false trackers.register("resolvers.cache", functi
local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
---[[ldx--
-<p>Once we found ourselves defining similar cache constructs
-several times, containers were introduced. Containers are used
-to collect tables in memory and reuse them when possible based
-on (unique) hashes (to be provided by the calling function).</p>
-
-<p>Caching to disk is disabled by default. Version numbers are
-stored in the saved table which makes it possible to change the
-table structures without bothering about the disk cache.</p>
-<p>Examples of usage can be found in the font related code.</p>
---ldx]]--
containers = containers or { }
local containers = containers
@@ -14670,11 +15415,7 @@ local trace_locating = false trackers.register("resolvers.locating", function(v
local report_zip = logs.reporter("resolvers","zip")
--- zip:///oeps.zip?name=bla/bla.tex
--- zip:///oeps.zip?tree=tex/texmf-local
--- zip:///texmf.zip?tree=/tex/texmf
--- zip:///texmf.zip?tree=/tex/texmf-local
--- zip:///texmf-mine.zip?tree=/tex/texmf-projects
+
local resolvers = resolvers
@@ -14999,7 +15740,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-crl'] = {
+if not modules then modules = { } end modules ['data-sch'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -15007,60 +15748,199 @@ if not modules then modules = { } end modules ['data-crl'] = {
license = "see context related readme files"
}
--- this one is replaced by data-sch.lua --
+local loadstring = loadstring
+local gsub, concat, format = string.gsub, table.concat, string.format
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
-local gsub = string.gsub
+local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end)
+local report_schemes = logs.reporter("resolvers","schemes")
-local resolvers = resolvers
+local http = require("socket.http")
+local ltn12 = require("ltn12")
-local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+local resolvers = resolvers
+local schemes = resolvers.schemes or { }
+resolvers.schemes = schemes
+
+local cleaners = { }
+schemes.cleaners = cleaners
+
+local threshold = 24 * 60 * 60
+
+directives.register("schemes.threshold", function(v) threshold = tonumber(v) or threshold end)
+
+function cleaners.none(specification)
+ return specification.original
+end
+
+function cleaners.strip(specification)
+ return (gsub(specification.original,"[^%a%d%.]+","-")) -- so we keep periods
+end
+
+function cleaners.md5(specification)
+ return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
+end
+
+local cleaner = cleaners.strip
+
+directives.register("schemes.cleanmethod", function(v) cleaner = cleaners[v] or cleaners.strip end)
+
+function resolvers.schemes.cleanname(specification)
+ local hash = cleaner(specification)
+ if trace_schemes then
+ report_schemes("hashing %s to %s",specification.original,hash)
+ end
+ return hash
+end
-resolvers.curl = resolvers.curl or { }
-local curl = resolvers.curl
+local cached, loaded, reused, thresholds, handlers = { }, { }, { }, { }, { }
-local cached = { }
+local function runcurl(name,cachename) -- we use sockets instead or the curl library when possible
+ local command = "curl --silent --create-dirs --output " .. cachename .. " " .. name
+ os.spawn(command)
+end
-local function runcurl(specification)
+local function fetch(specification)
local original = specification.original
- -- local scheme = specification.scheme
- local cleanname = gsub(original,"[^%a%d%.]+","-")
- local cachename = caches.setfirstwritablefile(cleanname,"curl")
+ local scheme = specification.scheme
+ local cleanname = schemes.cleanname(specification)
+ local cachename = caches.setfirstwritablefile(cleanname,"schemes")
if not cached[original] then
- if not io.exists(cachename) then
+ statistics.starttiming(schemes)
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > (thresholds[protocol] or threshold)) then
cached[original] = cachename
- local command = "curl --silent --create-dirs --output " .. cachename .. " " .. original
- os.spawn(command)
+ local handler = handlers[scheme]
+ if handler then
+ if trace_schemes then
+ report_schemes("fetching '%s', protocol '%s', method 'built-in'",original,scheme)
+ end
+ logs.flush()
+ handler(specification,cachename)
+ else
+ if trace_schemes then
+ report_schemes("fetching '%s', protocol '%s', method 'curl'",original,scheme)
+ end
+ logs.flush()
+ runcurl(original,cachename)
+ end
end
if io.exists(cachename) then
cached[original] = cachename
+ if trace_schemes then
+ report_schemes("using cached '%s', protocol '%s', cachename '%s'",original,scheme,cachename)
+ end
else
cached[original] = ""
+ if trace_schemes then
+ report_schemes("using missing '%s', protocol '%s'",original,scheme)
+ end
+ end
+ loaded[scheme] = loaded[scheme] + 1
+ statistics.stoptiming(schemes)
+ else
+ if trace_schemes then
+ report_schemes("reusing '%s', protocol '%s'",original,scheme)
end
+ reused[scheme] = reused[scheme] + 1
end
return cached[original]
end
--- old code: we could be cleaner using specification (see schemes)
-
local function finder(specification,filetype)
- return resolvers.methodhandler("finders",runcurl(specification),filetype)
+ return resolvers.methodhandler("finders",fetch(specification),filetype)
end
local opener = openers.file
local loader = loaders.file
-local function install(scheme)
- finders[scheme] = finder
- openers[scheme] = opener
- loaders[scheme] = loader
+local function install(scheme,handler,newthreshold)
+ handlers [scheme] = handler
+ loaded [scheme] = 0
+ reused [scheme] = 0
+ finders [scheme] = finder
+ openers [scheme] = opener
+ loaders [scheme] = loader
+ thresholds[scheme] = newthreshold or threshold
end
-resolvers.curl.install = install
+schemes.install = install
+
+local function http_handler(specification,cachename)
+ local tempname = cachename .. ".tmp"
+ local f = io.open(tempname,"wb")
+ local status, message = http.request {
+ url = specification.original,
+ sink = ltn12.sink.file(f)
+ }
+ if not status then
+ os.remove(tempname)
+ else
+ os.remove(cachename)
+ os.rename(tempname,cachename)
+ end
+ return cachename
+end
-install('http')
-install('https')
+install('http',http_handler)
+install('https') -- see pod
install('ftp')
+statistics.register("scheme handling time", function()
+ local l, r, nl, nr = { }, { }, 0, 0
+ for k, v in table.sortedhash(loaded) do
+ if v > 0 then
+ nl = nl + 1
+ l[nl] = k .. ":" .. v
+ end
+ end
+ for k, v in table.sortedhash(reused) do
+ if v > 0 then
+ nr = nr + 1
+ r[nr] = k .. ":" .. v
+ end
+ end
+ local n = nl + nr
+ if n > 0 then
+ l = nl > 0 and concat(l) or "none"
+ r = nr > 0 and concat(r) or "none"
+ return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
+ statistics.elapsedtime(schemes), n, threshold, l, r)
+ else
+ return nil
+ end
+end)
+
+-- We provide a few more helpers:
+
+----- http = require("socket.http")
+local httprequest = http.request
+local toquery = url.toquery
+
+-- local function httprequest(url)
+-- return os.resultof(format("curl --silent %q", url))
+-- end
+
+local function fetchstring(url,data)
+ local q = data and toquery(data)
+ if q then
+ url = url .. "?" .. q
+ end
+ local reply = httprequest(url)
+ return reply -- just one argument
+end
+
+schemes.fetchstring = fetchstring
+
+function schemes.fetchtable(url,data)
+ local reply = fetchstring(url,data)
+ if reply then
+ local s = loadstring("return " .. reply)
+ if s then
+ return s()
+ end
+ end
+end
+
end -- of closure
@@ -15074,170 +15954,199 @@ if not modules then modules = { } end modules ['data-lua'] = {
license = "see context related readme files"
}
--- some loading stuff ... we might move this one to slot 2 depending
--- on the developments (the loaders must not trigger kpse); we could
--- of course use a more extensive lib path spec
+-- We overload the regular loader. We do so because we operate mostly in
+-- tds and use our own loader code. Alternatively we could use a more
+-- extensive definition of package.path and package.cpath but even then
+-- we're not done. Also, we now have better tracing.
+--
+-- -- local mylib = require("libtest")
+-- -- local mysql = require("luasql.mysql")
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local concat = table.concat
+
+local trace_libraries = false
+
+trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+trackers.register("resolvers.locating", function(v) trace_libraries = v end)
local report_libraries = logs.reporter("resolvers","libraries")
local gsub, insert = string.gsub, table.insert
+local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
local unpack = unpack or table.unpack
+local is_readable = file.is_readable
local resolvers, package = resolvers, package
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
-local clibformats = { 'lib' }
-
-local _path_, libpaths, _cpath_, clibpaths
-
-function package.libpaths()
- if not _path_ or package.path ~= _path_ then
- _path_ = package.path
- libpaths = file.splitpath(_path_,";")
+local libsuffixes = { 'tex', 'lua' }
+local clibsuffixes = { 'lib' }
+local libformats = { 'TEXINPUTS', 'LUAINPUTS' }
+local clibformats = { 'CLUAINPUTS' }
+
+local libpaths = nil
+local clibpaths = nil
+local libhash = { }
+local clibhash = { }
+local libextras = { }
+local clibextras = { }
+
+local pattern = Cs(P("!")^0 / "" * (P("/") * P(-1) / "/" + P("/")^1 / "/" + 1)^0)
+
+local function cleanpath(path) --hm, don't we have a helper for this?
+ return resolvers.resolve(lpegmatch(pattern,path))
+end
+
+local function getlibpaths()
+ if not libpaths then
+ libpaths = { }
+ for i=1,#libformats do
+ local paths = resolvers.expandedpathlistfromvariable(libformats[i])
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not libhash[path] then
+ libpaths[#libpaths+1] = path
+ libhash[path] = true
+ end
+ end
+ end
end
return libpaths
end
-function package.clibpaths()
- if not _cpath_ or package.cpath ~= _cpath_ then
- _cpath_ = package.cpath
- clibpaths = file.splitpath(_cpath_,";")
+local function getclibpaths()
+ if not clibpaths then
+ clibpaths = { }
+ for i=1,#clibformats do
+ local paths = resolvers.expandedpathlistfromvariable(clibformats[i])
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not clibhash[path] then
+ clibpaths[#clibpaths+1] = path
+ clibhash[path] = true
+ end
+ end
+ end
end
return clibpaths
end
-local function thepath(...)
- local t = { ... } t[#t+1] = "?.lua"
- local path = file.join(unpack(t))
- if trace_locating then
- report_libraries("! appending '%s' to 'package.path'",path)
+package.libpaths = getlibpaths
+package.clibpaths = getclibpaths
+
+function package.extralibpath(...)
+ local paths = { ... }
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not libhash[path] then
+ if trace_libraries then
+ report_libraries("! extra lua path '%s'",path)
+ end
+ libextras[#libextras+1] = path
+ libpaths[#libpaths +1] = path
+ end
end
- return path
end
-local p_libpaths, a_libpaths = { }, { }
-
-function package.appendtolibpath(...)
- insert(a_libpath,thepath(...))
+function package.extraclibpath(...)
+ local paths = { ... }
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not clibhash[path] then
+ if trace_libraries then
+ report_libraries("! extra lib path '%s'",path)
+ end
+ clibextras[#clibextras+1] = path
+ clibpaths[#clibpaths +1] = path
+ end
+ end
end
-function package.prependtolibpath(...)
- insert(p_libpaths,1,thepath(...))
+if not package.loaders[-2] then
+ -- use package-path and package-cpath
+ package.loaders[-2] = package.loaders[2]
end
--- beware, we need to return a loadfile result !
+local function loadedaslib(resolved,rawname)
+ return package.loadlib(resolved,"luaopen_" .. gsub(rawname,"%.","_"))
+end
-local function loaded(libpaths,name,simple)
- for i=1,#libpaths do -- package.path, might become option
- local libpath = libpaths[i]
- local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
+local function loadedbylua(name)
+ if trace_libraries then
+ report_libraries("! locating %q using normal loader",name)
end
+ local resolved = package.loaders[-2](name)
end
-package.loaders[2] = function(name) -- was [#package.loaders+1]
- 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
+local function loadedbyformat(name,rawname,suffixes,islib)
+ if trace_libraries then
+ report_libraries("! locating %q as %q using formats %q",rawname,name,concat(suffixes))
end
- for i=1,#libformats do
- local format = libformats[i]
+ for i=1,#suffixes do -- so we use findfile and not a lookup loop
+ local format = suffixes[i]
local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
+ if trace_libraries then
+ report_libraries("! checking for %q' using format %q",name,format)
end
if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
+ if trace_libraries then
+ report_libraries("! lib %q located on %q",name,resolved)
end
- return loadfile(resolved)
- end
- end
- -- libpaths
- local libpaths, clibpaths = package.libpaths(), package.clibpaths()
- local simple = gsub(name,"%.lua$","")
- local simple = gsub(simple,"%.","/")
- local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple)
- if resolved then
- return resolved
- end
- --
- local libname = file.addsuffix(simple,os.libsuffix)
- for i=1,#clibformats do
- -- better have a dedicated loop
- local format = clibformats[i]
- local paths = resolvers.expandedpathlistfromvariable(format)
- for p=1,#paths do
- local path = paths[p]
- local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
- end
- return package.loadlib(resolved,name)
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
end
end
end
- for i=1,#clibpaths do -- package.path, might become option
- local libpath = clibpaths[i]
- local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
+end
+
+local function loadedbypath(name,rawname,paths,islib,what)
+ if trace_libraries then
+ report_libraries("! locating %q as %q on %q paths",rawname,name,what)
+ end
+ for p=1,#paths do
+ local path = paths[p]
+ local resolved = file.join(path,name)
+ if trace_libraries then -- mode detail
+ report_libraries("! checking for %q using %q path %q",name,what,path)
end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
+ if is_readable(resolved) then
+ if trace_libraries then
+ report_libraries("! lib %q located on %q",name,resolved)
+ end
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
end
- return package.loadlib(resolved,name)
- end
- end
- -- just in case the distribution is messed up
- if trace_loading then -- more detail
- report_libraries("! checking for '%s' using 'luatexlibs': '%s'",name)
- end
- local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
- if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
end
- return loadfile(resolved)
- end
- if trace_locating then
- report_libraries('? unable to locate lib: %s',name)
end
--- return "unable to locate " .. name
end
-resolvers.loadlualib = require
-
--- -- -- --
+local function notloaded(name)
+ if trace_libraries then
+ report_libraries("? unable to locate library %q",name)
+ end
+end
-package.obsolete = package.obsolete or { }
+package.loaders[2] = function(name)
+ local thename = gsub(name,"%.","/")
+ local luaname = file.addsuffix(thename,"lua")
+ local libname = file.addsuffix(thename,os.libsuffix)
+ return
+ loadedbyformat(luaname,name,libsuffixes, false)
+ or loadedbyformat(libname,name,clibsuffixes, true)
+ or loadedbypath (luaname,name,getlibpaths (),false,"lua")
+ or loadedbypath (luaname,name,getclibpaths(),false,"lua")
+ or loadedbypath (libname,name,getclibpaths(),true, "lib")
+ or loadedbylua (name)
+ or notloaded (name)
+end
-package.append_libpath = appendtolibpath -- will become obsolete
-package.prepend_libpath = prependtolibpath -- will become obsolete
+-- package.loaders[3] = nil
+-- package.loaders[4] = nil
-package.obsolete.append_libpath = appendtolibpath -- will become obsolete
-package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+resolvers.loadlualib = require
end -- of closure
@@ -15707,7 +16616,6 @@ function environment.make_format(name)
end
function environment.run_format(name,data,more)
- -- hm, rather old code here; we can now use the file.whatever functions
if name and name ~= "" then
local barename = file.removesuffix(name)
local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
@@ -15737,6 +16645,129 @@ end
end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['util-tpl'] = {
+ 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"
+}
+
+-- This is experimental code. Coming from dos and windows, I've always used %whatever%
+-- as template variables so let's stick to it. After all, it's easy to parse and stands
+-- out well. A double %% is turned into a regular %.
+
+utilities.templates = utilities.templates or { }
+local templates = utilities.templates
+
+local trace_template = false trackers.register("templates.trace",function(v) trace_template = v end)
+local report_template = logs.reporter("template")
+
+local format = string.format
+local P, C, Cs, Carg, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.Carg, lpeg.match
+
+-- todo: make installable template.new
+
+local replacer
+
+local function replacekey(k,t,recursive)
+ local v = t[k]
+ if not v then
+ if trace_template then
+ report_template("unknown key %q",k)
+ end
+ return ""
+ else
+ if trace_template then
+ report_template("setting key %q to value %q",k,v)
+ end
+ if recursive then
+ return lpegmatch(replacer,v,1,t)
+ else
+ return v
+ end
+ end
+end
+
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local escapers = {
+ lua = function(s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local function replacekeyunquoted(s,t,how,recurse) -- ".. \" "
+ local escaper = how and escapers[how] or escapers.lua
+ return escaper(replacekey(s,t,recurse))
+end
+
+local single = P("%") -- test %test% test : resolves test
+local double = P("%%") -- test 10%% test : %% becomes %
+local lquoted = P("%[") -- test %[test]" test : resolves test with escaped "'s
+local rquoted = P("]%") --
+
+local escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
+
+local key = nosingle * (C((1-nosingle)^1 * Carg(1) * Carg(2) * Carg(3))/replacekey) * nosingle
+local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2) * Carg(3))/replacekeyunquoted) * norquoted
+local any = P(1)
+
+ replacer = Cs((unquoted + escape + key + any)^0)
+
+local function replace(str,mapping,how,recurse)
+ if mapping then
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+ return str
+ end
+end
+
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] },'sql'))
+
+templates.replace = replace
+
+function templates.load(filename,mapping,how,recurse)
+ local data = io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+ return replace(data,mapping,how,recurse)
+ else
+ return data
+ end
+end
+
+function templates.resolve(t,mapping,how,recurse)
+ if not mapping then
+ mapping = t
+ end
+ for k, v in next, t do
+ t[k] = replace(v,mapping,how,recurse)
+ end
+ return t
+end
+
+-- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" }))
+-- inspect(utilities.templates.resolve({ one = "%two%", two = "two", three = "%three%" }))
+
+
+end -- of closure
-- end library merge
own = { } -- not local, might change
@@ -15796,7 +16827,7 @@ own.libs = { -- order can be made better
-- 'data-bin.lua',
'data-zip.lua',
'data-tre.lua',
- 'data-crl.lua',
+ 'data-sch.lua',
'data-lua.lua',
'data-aux.lua', -- updater
'data-tmf.lua',
@@ -15804,6 +16835,8 @@ own.libs = { -- order can be made better
'luat-sta.lua',
'luat-fmt.lua',
+
+ 'util-tpl.lua',
}
-- We need this hack till luatex is fixed.
@@ -15824,7 +16857,7 @@ own.path = gsub(match(own.name,"^(.+)[\\/].-$") or ".","\\","/")
local ownpath, owntree = own.path, environment and environment.ownpath or own.path
-own.list = {
+own.list = { -- predictable paths
'.',
ownpath ,
ownpath .. "/../sources", -- HH's development path
@@ -15848,7 +16881,7 @@ local function locate_libs()
local filename = pth .. "/" .. lib
local found = lfs.isfile(filename)
if found then
- package.path = package.path .. ";" .. pth .. "/?.lua" -- in case l-* does a require
+ package.path = package.path .. ";" .. pth .. "/?.lua" -- in case l-* does a require (probably obsolete)
return pth
end
end
@@ -15980,6 +17013,7 @@ local helpinfo = [[
--var-value report value of variable
--find-file report file location
--find-path report path of file
+--show-package-path report package paths
--pattern=str filter variables
]]
@@ -16093,7 +17127,8 @@ function runners.execute_script(fullname,internal,nosplit)
elseif state == 'skip' then
return true
elseif state == "run" then
- local path, name, suffix, result = file.dirname(fullname), file.basename(fullname), file.extname(fullname), ""
+ local path, name, suffix = file.splitname(fullname)
+ local result = ""
if path ~= "" then
result = fullname
elseif name then
@@ -16104,7 +17139,7 @@ function runners.execute_script(fullname,internal,nosplit)
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)
+ suffix = file.suffix(name)
end
if suffix == "" then
-- loop over known suffixes
@@ -16131,7 +17166,7 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local binary = runners.applications[file.extname(result)]
+ local binary = runners.applications[file.suffix(result)]
result = string.quoted(string.unquoted(result))
-- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
-- result = '"' .. result .. '"'
@@ -16324,7 +17359,7 @@ function resolvers.launch(str)
-- maybe we also need to test on mtxrun.launcher.suffix environment
-- variable or on windows consult the assoc and ftype vars and such
local launchers = runners.launchers[os.platform] if launchers then
- local suffix = file.extname(str) if suffix then
+ local suffix = file.suffix(str) if suffix then
local runner = launchers[suffix] if runner then
str = runner .. " " .. str
end
@@ -16383,7 +17418,7 @@ function runners.find_mtx_script(filename)
end
filename = file.addsuffix(filename,"lua")
local basename = file.removesuffix(file.basename(filename))
- local suffix = file.extname(filename)
+ local suffix = file.suffix(filename)
-- qualified path, raw name
local fullname = file.is_qualified_path(filename) and io.exists(filename) and filename
if fullname and fullname ~= "" then
@@ -16438,7 +17473,7 @@ function runners.execute_ctx_script(filename,...)
runners.register_arguments(...)
local arguments = environment.arguments_after
local fullname = runners.find_mtx_script(filename) or ""
- if file.extname(fullname) == "cld" then
+ if file.suffix(fullname) == "cld" then
-- handy in editors where we force --autopdf
report("running cld script: %s",filename)
table.insert(arguments,1,fullname)
@@ -16546,6 +17581,21 @@ function runners.timed(action)
statistics.timed(action)
end
+function runners.associate(filename)
+ os.launch(filename)
+end
+
+function runners.gethelp(filename)
+ local url = environment.argument("url")
+ if url and url ~= "" then
+ local command = string.gsub(environment.argument("command") or "unknown","^%s*\\*(.-)%s*$","%1")
+ url = utilities.templates.replace(url,{ command = command })
+ os.launch(url)
+ else
+ report("no --url given")
+ end
+end
+
-- this is a bit dirty ... first we store the first filename and next we
-- split the arguments so that we only see the ones meant for this script
-- ... later we will use the second half
@@ -16648,7 +17698,18 @@ else
end
-if e_argument("selfmerge") then
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
+
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
+
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -16671,23 +17732,25 @@ elseif e_argument("selfupdate") then
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif e_argument("ctxlua") or e_argument("internal") then
+elseif e_argument("show-package-path") or e_argument("show-package-paths") then
- -- run a script by loading it (using libs)
+ local l = package.libpaths()
+ local c = package.clibpaths()
- runners.loadbase()
- ok = runners.execute_script(filename,true)
+ for i=1,#l do
+ report("package lib path %s: %s",i,l[i])
+ end
-elseif e_argument("script") or e_argument("scripts") then
+ for i=1,#c do
+ report("package clib path %s: %s",i,c[i])
+ end
- -- run a script by loading it (using libs), pass args
+elseif e_argument("ctxlua") or e_argument("internal") then
+
+ -- run a script by loading it (using libs)
runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
+ ok = runners.execute_script(filename,true)
elseif e_argument("execute") then
@@ -16715,6 +17778,14 @@ elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
+elseif e_argument("associate") then
+
+ runners.associate(filename)
+
+elseif e_argument("gethelp") then
+
+ runners.gethelp()
+
elseif e_argument("makestubs") then
-- make stubs (depricated)
@@ -16806,7 +17877,7 @@ elseif e_argument("find-path") then
elseif e_argument("expand-braces") then
- -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename
+ -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
resolvers.load("nofiles")
runners.register_arguments(filename)
diff --git a/scripts/context/ruby/fcd_start.rb b/scripts/context/ruby/fcd_start.rb
deleted file mode 100644
index b1fa42a2a..000000000
--- a/scripts/context/ruby/fcd_start.rb
+++ /dev/null
@@ -1,472 +0,0 @@
-# Hans Hagen / PRAGMA ADE / 2005 / www.pragma-ade.com
-#
-# Fast Change Dir
-#
-# This is a kind of variant of the good old ncd
-# program. This script uses the same indirect cmd
-# trick as Erwin Waterlander's wcd program.
-#
-# === windows: fcd.cmd ===
-#
-# @echo off
-# ruby -S fcd_start.rb %1 %2 %3 %4 %5 %6 %7 %8 %9
-# if exist "%HOME%/fcd_stage.cmd" call %HOME%/fcd_stage.cmd
-#
-# === linux: fcd (fcd.sh) ===
-#
-# !/usr/bin/env sh
-# ruby -S fcd_start.rb $1 $2 $3 $4 $5 $6 $7 $8 $9
-# if test -f "$HOME/fcd_stage.sh" ; then
-# . $HOME/fcd_stage.sh ;
-# fi;
-#
-# ===
-#
-# On linux, one should source the file: ". fcd args" in order
-# to make the chdir persistent.
-#
-# You can create a stub with:
-#
-# ruby fcd_start.rb --stub --verbose
-#
-# usage:
-#
-# fcd --make t:\
-# fcd --add f:\project
-# fcd [--find] whatever
-# fcd [--find] whatever c (c being a list entry)
-# fcd [--find] whatever . (last choice with this pattern)
-# fcd --list
-
-# todo: HOMEDRIVE\HOMEPATH
-
-require 'rbconfig'
-
-class FastCD
-
- @@rootpath = nil
-
- ['HOME','TEMP','TMP','TMPDIR'].each do |key|
- if ENV[key] then
- if FileTest.directory?(ENV[key]) then
- @@rootpath = ENV[key]
- break
- end
- end
- end
-
- exit unless @@rootpath
-
- @@mswindows = Config::CONFIG['host_os'] =~ /mswin/
- @@maxlength = 26
-
- require 'Win32API' if @@mswindows
-
- if @@mswindows then
- @@stubcode = [
- '@echo off',
- '',
- 'if not exist "%HOME%" goto temp',
- '',
- ':home',
- '',
- 'ruby -S fcd_start.rb %1 %2 %3 %4 %5 %6 %7 %8 %9',
- '',
- 'if exist "%HOME%\fcd_stage.cmd" call %HOME%\fcd_stage.cmd',
- 'goto end',
- '',
- ':temp',
- '',
- 'ruby -S fcd_start.rb %1 %2 %3 %4 %5 %6 %7 %8 %9',
- '',
- 'if exist "%TEMP%\fcd_stage.cmd" call %TEMP%\fcd_stage.cmd',
- 'goto end',
- '',
- ':end'
- ].join("\n")
- else
- @@stubcode = [
- '#!/usr/bin/env sh',
- '',
- 'ruby -S fcd_start.rb $1 $2 $3 $4 $5 $6 $7 $8 $9',
- '',
- 'if test -f "$HOME/fcd_stage.sh" ; then',
- ' . $HOME/fcd_stage.sh ;',
- 'fi;'
- ].join("\n")
- end
-
- @@selfpath = File.dirname($0)
- @@datafile = File.join(@@rootpath,'fcd_state.dat')
- @@histfile = File.join(@@rootpath,'fcd_state.his')
- @@cdirfile = File.join(@@rootpath,if @@mswindows then 'fcd_stage.cmd' else 'fcd_stage.sh' end)
- @@stubfile = File.join(@@selfpath,if @@mswindows then 'fcd.cmd' else 'fcd' end)
-
- def initialize(verbose=false)
- @list = Array.new
- @hist = Hash.new
- @result = Array.new
- @pattern = ''
- @result = ''
- @verbose = verbose
- if f = File.open(@@cdirfile,'w') then
- f << "#{if @@mswindows then 'rem' else '#' end} no dir to change to"
- f.close
- else
- report("unable to create stub #{@@cdirfile}")
- end
- end
-
- def filename(name)
- File.join(@@root,name)
- end
-
- def report(str,verbose=@verbose)
- puts(">> #{str}") if verbose
- end
-
- def flush(str,verbose=@verbose)
- print(str) if verbose
- end
-
- def clear
- if FileTest.file?(@@histfile)
- begin
- File.delete(@@histfile)
- rescue
- report("error in deleting history file '#{@histfile}'")
- else
- report("history file '#{@histfile}' is deleted")
- end
- else
- report("no history file '#{@histfile}'")
- end
- end
-
- def scan(dir='.')
- begin
- [dir].flatten.sort.uniq.each do |dir|
- begin
- Dir.chdir(dir)
- report("scanning '#{dir}'")
- # flush(">> ")
- Dir.glob("**/*").each do |d|
- if FileTest.directory?(d) then
- @list << File.expand_path(d)
- # flush(".")
- end
- end
- # flush("\n")
- @list = @list.sort.uniq
- report("#{@list.size} entries found")
- rescue
- report("unknown directory '#{dir}'")
- end
- end
- rescue
- report("invalid dir specification ")
- end
- end
-
- def save
- begin
- if f = File.open(@@datafile,'w') then
- @list.each do |l|
- f.puts(l)
- end
- f.close
- report("#{@list.size} status bytes saved in #{@@datafile}")
- else
- report("unable to save status in #{@@datafile}")
- end
- rescue
- report("error in saving status in #{@@datafile}")
- end
- end
-
- def remember
- if @hist[@pattern] == @result then
- # no need to save result
- else
- begin
- if f = File.open(@@histfile,'w') then
- @hist[@pattern] = @result
- @hist.keys.each do |k|
- f.puts("#{k} #{@hist[k]}")
- end
- f.close
- report("#{@hist.size} history entries saved in #{@@histfile}")
- else
- report("unable to save history in #{@@histfile}")
- end
- rescue
- report("error in saving history in #{@@histfile}")
- end
- end
- end
-
- def load
- begin
- @list = IO.read(@@datafile).split("\n")
- report("#{@list.length} status bytes loaded from #{@@datafile}")
- rescue
- report("error in loading status from #{@@datafile}")
- end
- begin
- IO.readlines(@@histfile).each do |line|
- if line =~ /^(.*?)\s+(.*)$/i then
- @hist[$1] = $2
- end
- end
- report("#{@hist.length} history entries loaded from #{@@histfile}")
- rescue
- report("error in loading history from #{@@histfile}")
- end
- end
-
- def show
- begin
- puts("directories:")
- puts("\n")
- if @list.length > 0 then
- @list.each do |l|
- puts(l)
- end
- else
- puts("no entries")
- end
- puts("\n")
- puts("history:")
- puts("\n")
- if @hist.length > 0 then
- @hist.keys.sort.each do |h|
- puts("#{h} >> #{@hist[h]}")
- end
- else
- puts("no entries")
- end
- rescue
- end
- end
-
- def find(pattern=nil)
- begin
- if pattern = [pattern].flatten.first then
- if pattern.length > 0 and @pattern = pattern then
- @result = @list.grep(/\/#{@pattern}$/i)
- if @result.length == 0 then
- @result = @list.grep(/\/#{@pattern}[^\/]*$/i)
- end
- end
- else
- puts(Dir.pwd.gsub(/\\/o, '/'))
- end
- rescue
- puts("some error")
- end
- end
-
- def chdir(dir)
- begin
- if dir then
- if f = File.open(@@cdirfile,'w') then
- if @@mswindows then
- f.puts("cd /d #{dir.gsub('/','\\')}")
- else
- f.puts("cd #{dir.gsub("\\",'/')}")
- end
- f.close
- end
- @result = dir
- report("changing to #{dir}",true)
- else
- report("not changing dir")
- end
- rescue
- end
- end
-
- def choose(args=[])
- offset = 97
- unless @pattern.empty? then
- begin
- case @result.size
- when 0 then
- report("dir '#{@pattern}' not found",true)
- when 1 then
- chdir(@result[0])
- else
- list = @result.dup
- begin
- if answer = args[1] then # assignment & test
- if answer == '.' and @hist.key?(@pattern) then
- if FileTest.directory?(@hist[@pattern]) then
- print("last choice ")
- chdir(@hist[@pattern])
- return
- end
- else
- index = answer[0] - offset
- if dir = list[index] then
- chdir(dir)
- return
- end
- end
- end
- rescue
- puts("some error")
- end
- loop do
- print("\n")
- list.each_index do |i|
-begin
- if i < @@maxlength then
- # puts("#{(i+?a).chr} #{list[i]}")
- puts("#{(i+offset).chr} #{list[i]}")
- else
- puts("\n there are #{list.length-@@maxlength} entries more")
- break
- end
-rescue
- puts("some error")
-end
- end
- print("\n>> ")
- if answer = wait then
- if answer >= offset and answer <= offset+25 then
- index = answer - offset
- if dir = list[index] then
- print("#{answer.chr} ")
- chdir(dir)
- elsif @hist.key?(@pattern) and FileTest.directory?(@hist[@pattern]) then
- print("last choice ")
- chdir(@hist[@pattern])
- else
- print("quit\n")
- end
- break
- elsif list.length >= @@maxlength then
- @@maxlength.times do |i| list.shift end
- print("next set")
- print("\n")
- elsif @hist.key?(@pattern) and FileTest.directory?(@hist[@pattern]) then
- print("last choice ")
- chdir(@hist[@pattern])
- break
- else
- print("quit\n")
- break
- end
- end
- end
- end
- rescue
- report($!)
- end
- end
- end
-
- def wait
- begin
- $stdout.flush
- return getc
- rescue
- return nil
- end
- end
-
- def getc
- begin
- if @@mswindows then
- ch = Win32API.new('crtdll','_getch',[],'L').call
- else
- system('stty raw -echo')
- ch = $stdin.getc
- system('stty -raw echo')
- end
- rescue
- ch = nil
- end
- return ch
- end
-
- def check
- unless FileTest.file?(@@stubfile) then
- report("creating stub #{@@stubfile}")
- begin
- if f = File.open(@@stubfile,'w') then
- f.puts(@@stubcode)
- f.close
- end
- rescue
- report("unable to create stub #{@@stubfile}")
- else
- unless @mswindows then
- begin
- File.chmod(0755,@@stubfile)
- rescue
- report("unable to change protections on #{@@stubfile}")
- end
- end
- end
- else
- report("stub #{@@stubfile} already present")
- end
- end
-
-end
-
-$stdout.sync = true
-
-verbose, action, args = false, :find, Array.new
-
-usage = "fcd [--add|clear|find|list|make|show|stub] [--verbose] [pattern]"
-version = "1.0.2"
-
-def quit(message)
- puts(message)
- exit
-end
-
-ARGV.each do |a|
- case a
- when '-a', '--add' then action = :add
- when '-c', '--clear' then action = :clear
- when '-f', '--find' then action = :find
- when '-l', '--list' then action = :show
- when '-m', '--make' then action = :make
- when '-s', '--show' then action = :show
- when '--stub' then action = :stub
- when '-v', '--verbose' then verbose = true
- when '--version' then quit("version: #{version}")
- when '-h', '--help' then quit("usage: #{usage}")
- when /^\-\-.*/ then quit("error: unknown switch #{a}, try --help")
- else args << a
- end
-end
-
-fcd = FastCD.new(verbose)
-fcd.report("Fast Change Dir / version #{version}")
-
-case action
- when :make then
- fcd.clear
- fcd.scan(args)
- fcd.save
- when :clear then
- fcd.clear
- when :add then
- fcd.load
- fcd.scan(args)
- fcd.save
- when :show then
- fcd.load
- fcd.show
- when :find then
- fcd.load
- fcd.find(args)
- fcd.choose(args)
- fcd.remember
- when :stub
- fcd.check
-end
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index 108f2a8a1..e6bbbe2b5 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -8,6 +8,11 @@ if not modules then modules = { } end modules ['mtxrun'] = {
license = "see context related readme files"
}
+-- if not lpeg then require("lpeg") end
+-- if not md5 then require("md5") end
+-- if not lfs then require("lfs") end
+-- if not texconfig then texconfig = { } end
+
-- one can make a stub:
--
-- #!/bin/sh
@@ -150,11 +155,28 @@ function string.topattern(str,lowercase,strict)
end
end
+
+function string.valid(str,default)
+ return (type(str) == "string" and str ~= "" and str) or default or nil
+end
+
-- obsolete names:
string.quote = string.quoted
string.unquote = string.unquoted
+-- handy fallback
+
+string.itself = function(s) return s end
+
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -168,7 +190,8 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string
+local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local table, string = table, string
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
@@ -179,6 +202,8 @@ local getinfo = debug.getinfo
-- impact on ConTeXt was not that large; the remaining ipairs already
-- have been replaced. In a similar fashion we also hardly used pairs.
--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -238,12 +263,16 @@ function table.strip(tab)
end
function table.keys(t)
- local keys, k = { }, 0
- for key, _ in next, t do
- k = k + 1
- keys[k] = key
+ if t then
+ local keys, k = { }, 0
+ for key, _ in next, t do
+ k = k + 1
+ keys[k] = key
+ end
+ return keys
+ else
+ return { }
end
- return keys
end
local function compare(a,b)
@@ -256,41 +285,49 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
- for key,_ in next, tab do
- s = s + 1
- srt[s] = key
- if category == 3 then
- -- no further check
- else
- local tkey = type(key)
- if tkey == "string" then
- category = (category == 2 and 3) or 1
- elseif tkey == "number" then
- category = (category == 1 and 3) or 2
+ if tab then
+ local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ for key,_ in next, tab do
+ s = s + 1
+ srt[s] = key
+ if category == 3 then
+ -- no further check
else
- category = 3
+ local tkey = type(key)
+ if tkey == "string" then
+ category = (category == 2 and 3) or 1
+ elseif tkey == "number" then
+ category = (category == 1 and 3) or 2
+ else
+ category = 3
+ end
end
end
- end
- if category == 0 or category == 3 then
- sort(srt,compare)
+ if category == 0 or category == 3 then
+ sort(srt,compare)
+ else
+ sort(srt)
+ end
+ return srt
else
- sort(srt)
+ return { }
end
- return srt
end
local function sortedhashkeys(tab) -- fast one
- local srt, s = { }, 0
- for key,_ in next, tab do
- if key then
- s= s + 1
- srt[s] = key
+ if tab then
+ local srt, s = { }, 0
+ for key,_ in next, tab do
+ if key then
+ s= s + 1
+ srt[s] = key
+ end
end
+ sort(srt)
+ return srt
+ else
+ return { }
end
- sort(srt)
- return srt
end
table.sortedkeys = sortedkeys
@@ -315,7 +352,7 @@ end
table.sortedhash = sortedhash
table.sortedpairs = sortedhash
-function table.append(t, list)
+function table.append(t,list)
local n = #t
for i=1,#list do
n = n + 1
@@ -550,12 +587,26 @@ local function do_serialize(root,name,depth,level,indexed)
end
-- we could check for k (index) being number (cardinal)
if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- if compact then
+ -- -- NOT: for k=1,#root do (we need to quit at nil)
+ -- for k,v in ipairs(root) do -- can we use next?
+ -- if not first then first = k end
+ -- last = last + 1
+ -- end
+ -- end
+ local first, last = nil, 0
if compact then
- -- NOT: for k=1,#root do (we need to quit at nil)
- for k,v in ipairs(root) do -- can we use next?
- if not first then first = k end
- last = last + 1
+ last = #root
+ for k=1,last do
+-- if not root[k] then
+ if root[k] == nil then
+ last = k - 1
+ break
+ end
+ end
+ if last > 0 then
+ first = 1
end
end
local sk = sortedkeys(root)
@@ -1027,23 +1078,27 @@ function table.reversed(t)
end
end
-function table.sequenced(t,sep,simple) -- hash only
- local s, n = { }, 0
- for k, v in sortedhash(t) do
- if simple then
- if v == true then
- n = n + 1
- s[n] = k
- elseif v and v~= "" then
+function table.sequenced(t,sep) -- hash only
+ if t then
+ local s, n = { }, 0
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ n = n + 1
+ s[n] = k
+ elseif v and v~= "" then
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
+ end
+ else
n = n + 1
s[n] = k .. "=" .. tostring(v)
end
- else
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
end
+ return concat(s, sep or " | ")
+ else
+ return ""
end
- return concat(s, sep or " | ")
end
function table.print(t,...)
@@ -1124,6 +1179,8 @@ local lpeg = require("lpeg")
-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+-- some code will move to unicode and string
+
local report = texio and texio.write_nl or print
-- local lpmatch = lpeg.match
@@ -1160,8 +1217,8 @@ local report = texio and texio.write_nl or print
-- 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
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-- 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.
@@ -1169,9 +1226,8 @@ local byte, char, gmatch = string.byte, string.char, string.gmatch
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 P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
local utfcharacters = string.utfcharacters
local utfgmatch = unicode and unicode.utf8.gmatch
@@ -1222,6 +1278,10 @@ patterns.utf8char = utf8char
patterns.validutf8 = validutf8char
patterns.validutf8char = validutf8char
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+
patterns.digit = digit
patterns.sign = sign
patterns.cardinal = sign^0 * digit^1
@@ -1241,16 +1301,16 @@ 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.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
patterns.newline = newline
patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.nonspacer = 1 - spacer
+patterns.nonwhitespace = 1 - whitespace
patterns.equal = P("=")
patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.commaspacer = P(",") * spacer^0
patterns.period = P(".")
patterns.colon = P(":")
patterns.semicolon = P(";")
@@ -1265,6 +1325,10 @@ patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
@@ -1275,8 +1339,17 @@ patterns.beginline = #(1-newline)
-- 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?
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
end
function lpeg.splitter(pattern, action)
@@ -1325,7 +1398,7 @@ function string.splitup(str,separator)
if not separator then
separator = ","
end
- return match(splitters_m[separator] or splitat(separator),str)
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
end
@@ -1337,16 +1410,20 @@ function lpeg.split(separator,str)
c = tsplitat(separator)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
end
- return match(c,str)
end
local spacing = patterns.spacer^0 * newline -- sort of strip
@@ -1362,7 +1439,7 @@ local linesplitter = tsplitat(newline)
patterns.linesplitter = linesplitter
function string.splitlines(str)
- return match(linesplitter,str)
+ return lpegmatch(linesplitter,str)
end
local utflinesplitter = utfbom^-1 * tsplitat(newline)
@@ -1370,7 +1447,58 @@ local utflinesplitter = utfbom^-1 * tsplitat(newline)
patterns.utflinesplitter = utflinesplitter
function string.utfsplitlines(str)
- return match(utflinesplitter,str or "")
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
+local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
+
+function string.utfsplit(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+-- inspect(string.utfsplit("a b c d"))
+-- inspect(string.utfsplit("a b c d",true))
+
+-- -- alternative 1: 0.77
+--
+-- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
+--
+-- function string.utflength(str)
+-- return #lpegmatch(utfcharcounter,str or "")
+-- end
+--
+-- -- alternative 2: 1.70
+--
+-- local n = 0
+--
+-- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
+--
+-- function string.utflength(str)
+-- n = 0
+-- lpegmatch(utfcharcounter,str or "")
+-- return n
+-- end
+--
+-- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+local n = 0
+
+local utfcharcounter = utfbom^-1 * Cs ( (
+ Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+)^0 )
+
+function string.utflength(str)
+ n = 0
+ lpegmatch(utfcharcounter,str or "")
+ return n
end
@@ -1384,7 +1512,7 @@ function lpeg.checkedsplit(separator,str)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.checkedsplit(str,separator)
@@ -1395,7 +1523,7 @@ function string.checkedsplit(str,separator)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
@@ -1440,11 +1568,11 @@ function lpeg.keeper(str)
end
function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
+ return (P(str) + P(true)) * Cs(anything^0)
end
function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
+ return Cs((1 - P(str) * endofstring)^0)
end
-- Just for fun I looked at the used bytecode and
@@ -1453,8 +1581,22 @@ end
function lpeg.replacer(one,two)
if type(one) == "table" then
local no = #one
- if no > 0 then
- local p
+ local p
+ if no == 0 then
+ for k, v in next, one do
+ local pp = P(k) / v
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ return Cs(((1-one)^1 + one/two)^0)
+ else
for i=1,no do
local o = one[i]
local pp = P(o[1]) / o[2]
@@ -1467,11 +1609,16 @@ function lpeg.replacer(one,two)
return Cs((p + 1)^0)
end
else
+ one = P(one)
two = two or ""
- return Cs((P(one)/two + 1)^0)
+ return Cs(((1-one)^1 + one/two)^0)
end
end
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -1506,7 +1653,7 @@ local nany = utf8char/""
function lpeg.counter(pattern)
pattern = Cs((P(pattern)/" " + nany)^0)
return function(str)
- return #match(pattern,str)
+ return #lpegmatch(pattern,str)
end
end
@@ -1520,7 +1667,7 @@ if utfgmatch then
end
return n
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -1535,9 +1682,9 @@ else
p = Cs((P(what)/" " + nany)^0)
cache[p] = p
end
- return #match(p,str)
+ return #lpegmatch(p,str)
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -1564,7 +1711,7 @@ 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)
+ return lpegmatch(simple and s or p,str)
end
-- utf extensies
@@ -1611,7 +1758,7 @@ else
p = P(uc)
end
end
- match((utf8char/f)^0,str)
+ lpegmatch((utf8char/f)^0,str)
return p
end
@@ -1627,7 +1774,7 @@ function lpeg.UR(str,more)
first = str
last = more or first
else
- first, last = match(range,str)
+ first, last = lpegmatch(range,str)
if not last then
return P(str)
end
@@ -1654,11 +1801,15 @@ end
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
if type(list) ~= "table" then
list = { list, ... }
end
- -- sort(list) -- longest match first
+ -- table.sort(list) -- longest match first
local p = P(list[1])
for l=2,#list do
p = p + P(list[l])
@@ -1666,10 +1817,6 @@ function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
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.
@@ -1827,6 +1974,24 @@ end
-- utfchar(0x205F), -- math thinspace
-- } )
+-- handy from within tex:
+
+local lpegmatch = lpeg.match
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- strips leading and trailing spaces and collapsed all other spaces
+
+local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
+
+function string.collapsespaces(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -1851,14 +2016,14 @@ else
io.fileseparator, io.pathseparator = "/" , ":"
end
-function io.loaddata(filename,textmode)
+function io.loaddata(filename,textmode) -- return nil if empty
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
local data = f:read('*all')
f:close()
- return data
- else
- return nil
+ if #data > 0 then
+ return data
+ end
end
end
@@ -1880,6 +2045,45 @@ function io.savedata(filename,data,joiner)
end
end
+function io.loadlines(filename,n) -- return nil if empty
+ local f = io.open(filename,'r')
+ if f then
+ if n then
+ local lines = { }
+ for i=1,n do
+ local line = f:read("*lines")
+ if line then
+ lines[#lines+1] = line
+ else
+ break
+ end
+ end
+ f:close()
+ lines = concat(lines,"\n")
+ if #lines > 0 then
+ return lines
+ end
+ else
+ local line = f:read("*line") or ""
+ assert(f:close())
+ if #line > 0 then
+ return line
+ end
+ end
+ end
+end
+
+function io.loadchunk(filename,n)
+ local f = io.open(filename,'rb')
+ if f then
+ local data = f:read(n or 1024)
+ f:close()
+ if #data > 0 then
+ return data
+ end
+ end
+end
+
function io.exists(filename)
local f = io.open(filename)
if f == nil then
@@ -2107,7 +2311,7 @@ if not modules then modules = { } end modules ['l-number'] = {
-- this module will be replaced when we have the bit library
-local tostring = tostring
+local tostring, tonumber = tostring, tonumber
local format, floor, match, rep = string.format, math.floor, string.match, string.rep
local concat, insert = table.concat, table.insert
local lpegmatch = lpeg.match
@@ -2170,11 +2374,11 @@ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
end
function number.setbit(x, p)
- return hasbit(x, p) and x or x + p
+ return (x % (p + p) >= p) and x or x + p
end
function number.clearbit(x, p)
- return hasbit(x, p) and x - p or x
+ return (x % (p + p) >= p) and x - p or x
end
@@ -2208,6 +2412,10 @@ function number.tobitstring(n,m)
end
+function number.valid(str,default)
+ return tonumber(str) or default or nil
+end
+
end -- of closure
@@ -2319,17 +2527,28 @@ if not modules then modules = { } end modules ['l-os'] = {
-- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
-- os.platform : extended os.name with architecture
+-- os.sleep() => socket.sleep()
+-- math.randomseed(tonumber(string.sub(string.reverse(tostring(math.floor(socket.gettime()*10000))),1,6)))
+
-- maybe build io.flush in os.execute
local os = os
+local date, time = os.date, os.time
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
+local random, ceil, randomseed = math.random, math.ceil, math.randomseed
+local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring
-- The following code permits traversing the environment table, at least
-- in luatex. Internally all environment names are uppercase.
+-- The randomseed in Lua is not that random, although this depends on the operating system as well
+-- as the binary (Luatex is normally okay). But to be sure we set the seed anyway.
+
+math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+
+randomseed(math.initialseed)
+
if not os.__getenv__ then
os.__getenv__ = os.getenv
@@ -2433,12 +2652,14 @@ else
os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
+local launchers = {
+ windows = "start %s",
+ macosx = "open %s",
+ unix = "$BROWSER %s &> /dev/null &",
+}
+
function os.launch(str)
- if os.type == "windows" then
- os.execute("start " .. str) -- os.spawn ?
- else
- os.execute(str .. " &") -- os.spawn ?
- end
+ os.execute(format(launchers[os.name] or launchers.unix,str))
end
if not os.times then
@@ -2649,7 +2870,7 @@ end
local d
function os.timezone(delta)
- d = d or tonumber(tonumber(os.date("%H")-os.date("!%H")))
+ d = d or tonumber(tonumber(date("%H")-date("!%H")))
if delta then
if d > 0 then
return format("+%02i:00",d)
@@ -2661,6 +2882,44 @@ function os.timezone(delta)
end
end
+local timeformat = format("%%s%s",os.timezone(true))
+local dateformat = "!%Y-%m-%d %H:%M:%S"
+
+function os.fulltime(t,default)
+ t = tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = nil
+ end
+ return format(timeformat,date(dateformat,t))
+end
+
+local dateformat = "%Y-%m-%d %H:%M:%S"
+
+function os.localtime(t,default)
+ t = tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = nil
+ end
+ return date(dateformat,t)
+end
+
+function os.converttime(t,default)
+ local t = tonumber(t)
+ if t and t > 0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
+end
+
local memory = { }
local function which(filename)
@@ -2735,7 +2994,7 @@ local function nameonly(name)
return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$",""))
end
-local function extname(name,default)
+local function suffixonly(name,default)
return match(name,"^.+%.([^/\\]-)$") or default or ""
end
@@ -2744,11 +3003,16 @@ local function splitname(name)
return n or name, s or ""
end
-file.basename = basename
-file.dirname = dirname
-file.nameonly = nameonly
-file.extname = extname
-file.suffix = extname
+file.basename = basename
+
+file.pathpart = dirname
+file.dirname = dirname
+
+file.nameonly = nameonly
+
+file.suffixonly = suffixonly
+file.extname = suffixonly -- obsolete
+file.suffix = suffixonly
function file.removesuffix(filename)
return (gsub(filename,"%.[%a%d]+$",""))
@@ -2864,6 +3128,11 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
+function file.size(name)
+ local a = attributes(name)
+ return a and a.size or 0
+end
+
-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -3001,6 +3270,7 @@ local drive = C(R("az","AZ")) * P(":")
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 rest = C(P(1)^0)
drive = drive + Cc("")
path = path + Cc("")
@@ -3009,7 +3279,8 @@ 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)
+local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures
+local pattern_d = path * rest
function file.splitname(str,splitdrive)
if splitdrive then
@@ -3019,6 +3290,10 @@ function file.splitname(str,splitdrive)
end
end
+function file.splitbase(str)
+ return lpegmatch(pattern_d,str) -- returns path, base+suffix
+end
+
function file.nametotable(str,splitdrive) -- returns table
local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
if splitdrive then
@@ -3040,6 +3315,8 @@ function file.nametotable(str,splitdrive) -- returns table
end
end
+-- print(file.splitbase("a/b/c.txt"))
+
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
--
-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
@@ -3081,15 +3358,30 @@ if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
-function file.needs_updating(oldname,newname,threshold) -- size modification access change
- local oldtime = lfs.attributes(oldname, modification)
- local newtime = lfs.attributes(newname, modification)
- if newtime >= oldtime then
- return false
- elseif oldtime - newtime < (threshold or 1) then
- return false
+function file.needsupdating(oldname,newname,threshold) -- size modification access change
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime = lfs.attributes(newname,"modification")
+ if not newtime then
+ return true -- no new file, so no updating needed
+ elseif newtime >= oldtime then
+ return false -- new file definitely needs updating
+ elseif oldtime - newtime < (threshold or 1) then
+ return false -- new file is probably still okay
+ else
+ return true -- new file has to be updated
+ end
else
- return true
+ return false -- no old file, so no updating needed
+ end
+end
+
+file.needs_updating = file.needsupdating
+
+function file.syncmtimes(oldname,newname)
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
end
end
@@ -3111,7 +3403,7 @@ function file.loadchecksum(name)
return nil
end
-function file.savechecksum(name, checksum)
+function file.savechecksum(name,checksum)
if not checksum then checksum = file.checksum(name) end
if checksum then
io.savedata(name .. ".md5",checksum)
@@ -3136,7 +3428,7 @@ if not modules then modules = { } end modules ['l-url'] = {
local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find
local concat = table.concat
local tonumber, type = tonumber, type
-local P, C, R, S, Cs, Cc, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct
+local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V
local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer
-- from wikipedia:
@@ -3169,15 +3461,19 @@ local endofstring = P(-1)
local hexdigit = R("09","AF","af")
local plus = P("+")
local nothing = Cc("")
-local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
+local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar
+local escaped = (plus / " ") + escapedchar
-- 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
+--
+-- maybe we should already split the query (better for unescaping as = & can be part of a value
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)
+----- querystr = Cs((escaped+(1- hash))^0)
+local querystr = Cs(( (1- hash))^0)
local fragmentstr = Cs((escaped+(1- endofstring))^0)
local scheme = schemestr * colon + nothing
@@ -3192,11 +3488,20 @@ local parser = Ct(validurl)
lpegpatterns.url = validurl
lpegpatterns.urlsplitter = parser
-local escapes = { } ; for i=0,255 do escapes[i] = format("%%%02X",i) end
+local escapes = { }
+
+setmetatable(escapes, { __index = function(t,k)
+ local v = format("%%%02X",byte(k))
+ t[k] = v
+ return v
+end })
-local escaper = Cs((R("09","AZ","az") + S("-./_") + P(1) / escapes)^0)
+local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most
+local unescaper = Cs((escapedchar + 1)^0)
-lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaped = escapedchar
+lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaper = unescaper
-- todo: reconsider Ct as we can as well have five return values (saves a table)
-- so we can have two parsers, one with and one without
@@ -3208,8 +3513,12 @@ end
local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
local function hasscheme(str)
- local scheme = lpegmatch(isscheme,str) -- at least one character
- return scheme ~= "" and scheme or false
+ if str then
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
+ else
+ return false
+ end
end
@@ -3228,10 +3537,32 @@ local rootbased = P("/")
local barswapper = replacer("|",":")
local backslashswapper = replacer("\\","/")
+-- queries:
+
+local equal = P("=")
+local amp = P("&")
+local key = Cs(((escapedchar+1)-equal )^0)
+local value = Cs(((escapedchar+1)-amp -endofstring)^0)
+
+local splitquery = Cf ( Ct("") * P { "sequence",
+ sequence = V("pair") * (amp * V("pair"))^0,
+ pair = Cg(key * equal * value),
+}, rawset)
+
+-- hasher
+
local function hashed(str) -- not yet ok (/test?test)
+ if str == "" then
+ return {
+ scheme = "invalid",
+ original = str,
+ }
+ end
local s = split(str)
- local somescheme = s[1] ~= ""
- local somequery = s[4] ~= ""
+ local rawscheme = s[1]
+ local rawquery = s[4]
+ local somescheme = rawscheme ~= ""
+ local somequery = rawquery ~= ""
if not somescheme and not somequery then
s = {
scheme = "file",
@@ -3247,14 +3578,17 @@ local function hashed(str) -- not yet ok (/test?test)
local authority, path, filename = s[2], s[3]
if authority == "" then
filename = path
+ elseif path == "" then
+ filename = ""
else
filename = authority .. "/" .. path
end
s = {
- scheme = s[1],
+ scheme = rawscheme,
authority = authority,
path = path,
- query = s[4],
+ query = lpegmatch(unescaper,rawquery), -- unescaped, but possible conflict with & and =
+ queries = lpegmatch(splitquery,rawquery), -- split first and then unescaped
fragment = s[5],
original = str,
noscheme = false,
@@ -3264,6 +3598,8 @@ local function hashed(str) -- not yet ok (/test?test)
return s
end
+-- inspect(hashed("template://test"))
+
-- Here we assume:
--
-- files: /// = relative
@@ -3306,23 +3642,65 @@ function url.construct(hash) -- dodo: we need to escape !
return lpegmatch(escaper,concat(fullurl))
end
-function url.filename(filename)
+function url.filename(filename) -- why no lpeg here ?
local t = hashed(filename)
return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename
end
+local function escapestring(str)
+ return lpegmatch(escaper,str)
+end
+
+url.escape = escapestring
+
+-- function url.query(str) -- separator could be an option
+-- if type(str) == "string" then
+-- local t = { }
+-- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
+-- t[k] = v
+-- end
+-- return t
+-- else
+-- return str
+-- end
+-- end
+
function url.query(str)
if type(str) == "string" then
- local t = { }
- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
- t[k] = v
- end
- return t
+ return lpegmatch(splitquery,str) or ""
else
return str
end
end
+function url.toquery(data)
+ local td = type(data)
+ if td == "string" then
+ return #str and escape(data) or nil -- beware of double escaping
+ elseif td == "table" then
+ if next(data) then
+ local t = { }
+ for k, v in next, data do
+ t[#t+1] = format("%s=%s",k,escapestring(v))
+ end
+ return concat(t,"&")
+ end
+ else
+ -- nil is a signal that no query
+ end
+end
+
+-- /test/ | /test | test/ | test => test
+
+function url.barepath(path)
+ if not path or path == "" then
+ return ""
+ else
+ return (gsub(path,"^/?(.-)/?$","%1"))
+ end
+end
+
+
@@ -3363,6 +3741,24 @@ local isdir = lfs.isdir
local isfile = lfs.isfile
local currentdir = lfs.currentdir
+-- in case we load outside luatex
+
+if not isdir then
+ function isdir(name)
+ local a = attributes(name)
+ return a and a.mode == "directory"
+ end
+ lfs.isdir = isdir
+end
+
+if not isfile then
+ function isfile(name)
+ local a = attributes(name)
+ return a and a.mode == "file"
+ end
+ lfs.isfile = isfile
+end
+
-- handy
function dir.current()
@@ -3738,28 +4134,49 @@ function boolean.tonumber(b)
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
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
elseif str == "true" then
return true
elseif str == "false" then
return false
+ elseif not tolerant then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
else
- return str
+ return str == "yes" or str == "on" or str == "t"
end
end
string.toboolean = toboolean
+function string.booleanstring(str)
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
+ else
+ return str == "yes" or str == "on" or str == "t"
+ end
+end
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -3784,57 +4201,229 @@ if not modules then modules = { } end modules ['l-unicode'] = {
license = "see context related readme files"
}
+-- this module will be reorganized
+
+-- todo: utf.sub replacement (used in syst-aux)
+
+local concat = table.concat
+local type = type
+local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local utftype = patterns.utftype
+local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
+local utfsplitlines = string.utfsplitlines
+
if not unicode then
- unicode = { utf8 = { } }
+ unicode = { }
+
+end
+
+local unicode = unicode
+
+utf = utf or unicode.utf8
+
+if not utf then
+
+ utf8 = { }
+ unicode.utf8 = utf8
+ utf = utf8
+
+end
+
+if not utf.char then
local floor, char = math.floor, string.char
- function unicode.utf8.utfchar(n)
+ function utf.char(n)
if n < 0x80 then
+ -- 0aaaaaaa : 0x80
return char(n)
elseif n < 0x800 then
+ -- 110bbbaa : 0xC0 : n >> 6
+ -- 10aaaaaa : 0x80 : n & 0x3F
return char(
0xC0 + floor(n/0x40),
0x80 + (n % 0x40)
)
elseif n < 0x10000 then
+ -- 1110bbbb : 0xE0 : n >> 12
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
return char(
0xE0 + floor(n/0x1000),
0x80 + (floor(n/0x40) % 0x40),
0x80 + (n % 0x40)
)
- elseif n < 0x40000 then
+ elseif n < 0x200000 then
+ -- 11110ccc : 0xF0 : n >> 18
+ -- 10ccbbbb : 0x80 : (n >> 12) & 0x3F
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
+ -- dddd : ccccc - 1
return char(
- 0xF0 + floor(n/0x40000),
- 0x80 + floor(n/0x1000),
+ 0xF0 + floor(n/0x40000),
+ 0x80 + (floor(n/0x1000) % 0x40),
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 "?"
+ return ""
end
end
end
-local unicode = unicode
+if not utf.byte then
+
+ local utf8byte = patterns.utf8byte
+
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+
+end
+
+local utfchar, utfbyte = utf.char, utf.byte
+
+-- As we want to get rid of the (unmaintained) utf library we implement our own
+-- variants (in due time an independent module):
+
+function unicode.filetype(data)
+ return data and lpegmatch(utftype,data) or "unknown"
+end
+
+local toentities = 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
-utf = utf or unicode.utf8
-local concat = table.concat
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
-local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-local type = type
-local utfsplitlines = string.utfsplitlines
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+-- actually one of them is already utf ... sort of useless this one
+
+-- function utf.char(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
+--
+-- merge into:
+
+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
+
+local validatedutf = Cs (
+ (
+ patterns.utf8one
+ + patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ + P(1) / "�"
+ )^0
+)
+
+patterns.validatedutf = validatedutf
+
+function string.validutf(str)
+ return lpegmatch(validatedutf,str)
+end
+
+
+utf.length = string.utflength
+utf.split = string.utfsplit
+utf.splitines = string.utfsplitlines
+utf.valid = string.validutf
+
+if not utf.len then
+ utf.len = utf.length
+end
+
+-- a replacement for simple gsubs:
+
+local utf8char = patterns.utf8char
+
+function utf.remapper(mapping)
+ local pattern = Cs((utf8char/mapping)^0)
+ return function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end, pattern
+end
+
+-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
+-- print(remap("abcd 1234 abcd"))
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
@@ -4027,11 +4616,22 @@ local function big(c)
end
end
+-- function unicode.utf8_to_utf16(str,littleendian)
+-- if littleendian then
+-- return char(255,254) .. utfgsub(str,".",little)
+-- else
+-- return char(254,255) .. utfgsub(str,".",big)
+-- end
+-- end
+
+local _, l_remap = utf.remapper(little)
+local _, b_remap = utf.remapper(big)
+
function unicode.utf8_to_utf16(str,littleendian)
if littleendian then
- return char(255,254) .. utfgsub(str,".",little)
+ return char(255,254) .. lpegmatch(l_remap,str)
else
- return char(254,255) .. utfgsub(str,".",big)
+ return char(254,255) .. lpegmatch(b_remap,str)
end
end
@@ -4052,84 +4652,12 @@ function unicode.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
+--
-local lpegmatch = lpeg.match
-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)
-
--- actually one of them is already utf ... sort of useless this one
-
-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
-
-local validatedutf = Cs (
- (
- patterns.utf8one
- + patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- + P(1) / "�"
- )^0
-)
-
-patterns.validatedutf = validatedutf
+local pattern = Ct(C(patterns.utf8char)^0)
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
+function utf.totable(str)
+ return lpegmatch(pattern,str)
end
@@ -4189,10 +4717,11 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch, rep = string.format, string.gmatch, string.rep
+local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub
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
+local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring
+local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -4346,6 +4875,121 @@ function tables.encapsulate(core,capsule,protect)
end
end
+local function serialize(t,r,outer) -- no mixes
+ r[#r+1] = "{"
+ local n = #t
+ if n > 0 then
+ for i=1,n do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("%q,",v)
+ elseif tv == "number" then
+ r[#r+1] = format("%s,",v)
+ elseif tv == "table" then
+ serialize(v,r)
+ elseif tv == "boolean" then
+ r[#r+1] = format("%s,",tostring(v))
+ end
+ end
+ else
+ for k, v in next, t do
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("[%q]=%q,",k,v)
+ elseif tv == "number" then
+ r[#r+1] = format("[%q]=%s,",k,v)
+ elseif tv == "table" then
+ r[#r+1] = format("[%q]=",k)
+ serialize(v,r)
+ elseif tv == "boolean" then
+ r[#r+1] = format("[%q]=%s,",k,tostring(v))
+ end
+ end
+ end
+ if outer then
+ r[#r+1] = "}"
+ else
+ r[#r+1] = "},"
+ end
+ return r
+end
+
+function table.fastserialize(t,prefix)
+ return concat(serialize(t,{ prefix or "return" },true))
+end
+
+function table.deserialize(str)
+ if not str or str == "" then
+ return
+ end
+ local code = loadstring(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
+end
+
+-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
+
+function table.load(filename)
+ if filename then
+ local t = io.loaddata(filename)
+ if t and t ~= "" then
+ t = loadstring(t)
+ if type(t) == "function" then
+ t = t()
+ if type(t) == "table" then
+ return t
+ end
+ end
+ end
+ end
+end
+
+local function slowdrop(t)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = format("%s=%q",k,v)
+ end
+ r[i] = format(" {%s},\n",concat(l))
+ end
+ return format("return {\n%s}",concat(r))
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ for i=1,#t do
+ local ti = t[i]
+ r[#r+1] = " {"
+ for k, v in next, ti do
+ r[#r+1] = format("%s=%q",k,v)
+ end
+ r[#r+1] = "},\n"
+ end
+ r[#r+1] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow)
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
+
end -- of closure
@@ -4520,11 +5164,10 @@ local concat = table.concat
local type, next = type, next
utilities = utilities or {}
-utilities.merger = utilities.merger or { } -- maybe mergers
+local merger = utilities.merger or { }
+utilities.merger = merger
utilities.report = logs and logs.reporter("system") or print
-local merger = utilities.merger
-
merger.strip_comment = true
local m_begin_merge = "begin library merge"
@@ -4570,9 +5213,11 @@ end
local function self_save(name, data)
if data ~= "" then
if merger.strip_comment then
- -- saves some 20K
local n = #data
+ -- saves some 20K .. scite comments
data = gsub(data,"%-%-~[^\n\r]*[\r\n]","")
+ -- saves some 20K .. ldx comments
+ data = gsub(data,"%-%-%[%[ldx%-%-.-%-%-ldx%]%]%-%-","")
utilities.report("merge: %s bytes of comment stripped, %s bytes of code left",n-#data,#data)
end
io.savedata(name,data)
@@ -4653,36 +5298,208 @@ if not modules then modules = { } end modules ['util-lua'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment = "the strip code is written by Peter Cawley",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-utilities = utilities or {}
-utilities.lua = utilities.lua or { }
-utilities.report = logs and logs.reporter("system") or print
+local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
+local loadstring, loadfile, type = loadstring, loadfile, type
-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)
+utilities = utilities or {}
+utilities.lua = utilities.lua or { }
+local luautilities = utilities.lua
+
+utilities.report = logs and logs.reporter("system") or print -- can be overloaded later
+
+local tracestripping = false
+local forcestupidcompile = true -- use internal bytecode compiler
+luautilities.stripcode = true -- support stripping when asked for
+luautilities.alwaysstripcode = false -- saves 1 meg on 7 meg compressed format file (2012.08.12)
+luautilities.nofstrippedchunks = 0
+luautilities.nofstrippedbytes = 0
+
+-- The next function was posted by Peter Cawley on the lua list and strips line
+-- number information etc. from the bytecode data blob. We only apply this trick
+-- when we store data tables. Stripping makes the compressed format file about
+-- 1MB smaller (and uncompressed we save at least 6MB).
+--
+-- You can consider this feature an experiment, so it might disappear. There is
+-- no noticeable gain in runtime although the memory footprint should be somewhat
+-- smaller (and the file system has a bit less to deal with).
+--
+-- Begin of borrowed code ... works for Lua 5.1 which LuaTeX currently uses ...
+
+local function strip_code_pc(dump,name)
+ local before = #dump
+ local version, format, endian, int, size, ins, num = byte(dump,5,11)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
end
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
+ end
+ end
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ end
+ end
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. sub(dump,dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(sub(dump,offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
+ end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. rep("\0", int * 3)
+ return stripped, offset
+ end
+ dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
+ local after = #dump
+ local delta = before-after
+ if tracestripping then
+ utilities.report("stripped bytecode: %s, before %s, after %s, delta %s",name or "unknown",before,after,delta)
+ end
+ luautilities.nofstrippedchunks = luautilities.nofstrippedchunks + 1
+ luautilities.nofstrippedbytes = luautilities.nofstrippedbytes + delta
+ return dump, delta
+end
+
+-- ... end of borrowed code.
+
+local function strippedbytecode(code,forcestrip,name)
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ return strip_code_pc(code,name)
+ else
+ return code, 0
end
end
-function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
+luautilities.stripbytecode = strip_code_pc
+luautilities.strippedbytecode = strippedbytecode
+
+local function fatalerror(name)
+ utilities.report(format("fatal error in %q",name or "unknown"))
+end
+
+-- quite subtle ... doing this wrong incidentally can give more bytes
+
+
+function luautilities.loadedluacode(fullname,forcestrip,name)
+ -- quite subtle ... doing this wrong incidentally can give more bytes
+ name = name or fullname
+ local code = loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip) == "function" then
+ forcestrip = forcestrip(fullname)
+ end
+ if forcestrip then
+ local code, n = strip_code_pc(dump(code,name))
+ return loadstring(code), n
+ elseif luautilities.alwaysstripcode then
+ return loadstring(strip_code_pc(dump(code),name))
+ else
+ return code, 0
+ end
+ elseif luautilities.alwaysstripcode then
+ return loadstring(strip_code_pc(dump(code),name))
+ else
+ return code, 0
+ end
+end
+
+function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
+ local n = 0
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ code = loadstring(code)
+ if not code then
+ fatalerror(name)
+ end
+ code, n = strip_code_pc(dump(code),name)
+ end
+ return loadstring(code), n
+end
+
+local function stupidcompile(luafile,lucfile,strip)
+ local code = io.loaddata(luafile)
+ local n = 0
+ if code and code ~= "" then
+ code = loadstring(code)
+ if not code then
+ fatalerror()
+ end
+ code = dump(code)
+ if strip then
+ code, n = strippedbytecode(code,true,luafile) -- last one is reported
+ end
+ if code and code ~= "" then
+ io.savedata(lucfile,code)
+ end
+ end
+ return n
+end
+
+local luac_normal = "texluac -o %q %q"
+local luac_strip = "texluac -s -o %q %q"
+
+function luautilities.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)
+ local done = false
if strip ~= false then
- command = "-s " .. command
+ strip = true
+ end
+ if forcestupidcompile then
+ fallback = true
+ elseif strip then
+ done = os.spawn(format(luac_strip, lucfile,luafile)) == 0
+ else
+ done = os.spawn(format(luac_normal,lucfile,luafile)) == 0
end
- 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
+ local n = stupidcompile(luafile,lucfile,strip)
+ if n > 0 then
+ utilities.report("lua: %s dumped into %s (%i bytes stripped)",luafile,lucfile,n)
+ else
+ utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile)
+ end
+ cleanup = false -- better see how bad it is
end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
@@ -4697,7 +5514,6 @@ end
-
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -4710,8 +5526,10 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-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 lpeg, table, string = lpeg, table, string
+
+local P, R, V, S, C, Ct, Cs, Carg, Cc = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
@@ -4723,29 +5541,39 @@ parsers.patterns = parsers.patterns or { }
local setmetatableindex = table.setmetatableindex
local sortedhash = table.sortedhash
+-- we share some patterns
+
+local space = P(' ')
+local equal = P("=")
+local comma = P(",")
+local lbrace = P("{")
+local rbrace = P("}")
+local period = S(".")
+local punctuation = S(".,:;")
+local spacer = patterns.spacer
+local whitespace = patterns.whitespace
+local newline = patterns.newline
+local anything = patterns.anything
+local endofstring = patterns.endofstring
+
-- we could use a Cf Cg construct
local escape, left, right = P("\\"), P('{'), P('}')
-lpeg.patterns.balanced = P {
+patterns.balanced = P {
[1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0,
[2] = left * V(1) * right
}
-local space = P(' ')
-local equal = P("=")
-local comma = P(",")
-local lbrace = P("{")
-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
+local content = (1-endofstring)^0
-lpeg.patterns.nested = nested -- no capture
-lpeg.patterns.argument = argument -- argument after e.g. =
-lpeg.patterns.content = content -- rest after e.g =
+patterns.nested = nested -- no capture
+patterns.argument = argument -- argument after e.g. =
+patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4764,10 +5592,6 @@ local function set(key,value)
hash[key] = value
end
-local function set(key,value)
- hash[key] = value
-end
-
local pattern_a_s = (pattern_a/set)^1
local pattern_b_s = (pattern_b/set)^1
local pattern_c_s = (pattern_c/set)^1
@@ -4818,7 +5642,7 @@ end
local separator = comma * space^0
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-local pattern = Ct(value*(separator*value)^0)
+local pattern = spaces * Ct(value*(separator*value)^0)
-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
@@ -4942,6 +5766,37 @@ function parsers.listitem(str)
return gmatch(str,"[^, ]+")
end
+--
+local digit = R("09")
+
+local pattern = Cs { "start",
+ start = V("one") + V("two") + V("three"),
+ rest = (Cc(",") * V("thousand"))^0 * (P(".") + endofstring) * anything^0,
+ thousand = digit * digit * digit,
+ one = digit * V("rest"),
+ two = digit * digit * V("rest"),
+ three = V("thousand") * V("rest"),
+}
+
+patterns.splitthousands = pattern -- maybe better in the parsers namespace ?
+
+function parsers.splitthousands(str)
+ return lpegmatch(pattern,str) or str
+end
+
+-- print(parsers.splitthousands("11111111111.11"))
+
+local optionalwhitespace = whitespace^0
+
+patterns.words = Ct((Cs((1-punctuation-whitespace)^1) + anything)^1)
+patterns.sentences = Ct((optionalwhitespace * Cs((1-period)^0 * period))^1)
+patterns.paragraphs = Ct((optionalwhitespace * Cs((whitespace^1*endofstring/"" + 1 - (spacer^0*newline*newline))^1))^1)
+
+-- local str = " Word1 word2. \n Word3 word4. \n\n Word5 word6.\n "
+-- inspect(lpegmatch(patterns.paragraphs,str))
+-- inspect(lpegmatch(patterns.sentences,str))
+-- inspect(lpegmatch(patterns.words,str))
+
end -- of closure
@@ -5043,7 +5898,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util.deb'] = {
+if not modules then modules = { } end modules ['util-deb'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -5155,6 +6010,7 @@ function inspect(i) -- global function
else
print(tostring(i))
end
+ return i -- so that we can inline the inspect
end
-- from the lua book:
@@ -5194,7 +6050,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
-local write_nl = texio.write_nl
+local write_nl = texio and texio.write_nl or print
statistics = statistics or { }
local statistics = statistics
@@ -5277,7 +6133,7 @@ statistics.elapsedtime = elapsedtime
statistics.elapsedindeed = elapsedindeed
statistics.elapsedseconds = elapsedseconds
--- general function
+-- general function .. we might split this module
function statistics.register(tag,fnc)
if statistics.enable and type(fnc) == "function" then
@@ -5387,6 +6243,8 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
license = "see context related readme files"
}
+-- maybe this should be util-set.lua
+
local type, next, tostring = type, next, tostring
local concat = table.concat
local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
@@ -5586,7 +6444,7 @@ function setters.show(t)
local value, default, modules = functions.value, functions.default, #functions
value = value == nil and "unset" or tostring(value)
default = default == nil and "unset" or tostring(default)
- t.report("%-30s modules: %2i default: %6s value: %6s",name,modules,default,value)
+ t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value)
end
end
t.report()
@@ -5678,17 +6536,31 @@ end)
-- experiment
-local flags = environment and environment.engineflags
+if environment then
-if flags then
- if trackers and flags.trackers then
- setters.initialize("flags","trackers", settings_to_hash(flags.trackers))
- -- t_enable(flags.trackers)
- end
- if directives and flags.directives then
- setters.initialize("flags","directives", settings_to_hash(flags.directives))
- -- d_enable(flags.directives)
+ -- The engineflags are known earlier than environment.arguments but maybe we
+ -- need to handle them both as the later are parsed differently. The c: prefix
+ -- is used by mtx-context to isolate the flags from those that concern luatex.
+
+ local engineflags = environment.engineflags
+
+ if engineflags then
+ if trackers then
+ local list = engineflags["c:trackers"] or engineflags["trackers"]
+ if type(list) == "string" then
+ setters.initialize("flags","trackers",settings_to_hash(list))
+ -- t_enable(list)
+ end
+ end
+ if directives then
+ local list = engineflags["c:directives"] or engineflags["directives"]
+ if type(list) == "string" then
+ setters.initialize("flags","directives", settings_to_hash(list))
+ -- d_enable(list)
+ end
+ end
end
+
end
-- here
@@ -5741,10 +6613,7 @@ local next, type = next, type
local setmetatableindex = table.setmetatableindex
---[[ldx--
-<p>This is a prelude to a more extensive logging module. We no longer
-provide <l n='xml'/> based logging a sparsing is relatively easy anyway.</p>
---ldx]]--
+
logs = logs or { }
local logs = logs
@@ -6560,7 +7429,8 @@ local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
local unquoted, quoted = string.unquoted, string.quoted
-local concat = table.concat
+local concat, insert, remove = table.concat, table.insert, table.remove
+local loadedluacode = utilities.lua.loadedluacode
-- precautions
@@ -6578,8 +7448,28 @@ if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaon
for k=3,#arg do
arg[k-2] = arg[k]
end
- arg[#arg] = nil -- last
- arg[#arg] = nil -- pre-last
+ remove(arg) -- last
+ remove(arg) -- pre-last
+end
+
+-- This is an ugly hack but it permits symlinking a script (say 'context') to 'mtxrun' as in:
+--
+-- ln -s /opt/minimals/tex/texmf-linux-64/bin/mtxrun context
+--
+-- The special mapping hack is needed because 'luatools' boils down to 'mtxrun --script base'
+-- but it's unlikely that there will be more of this
+
+do
+
+ local originalzero = file.basename(arg[0])
+ local specialmapping = { luatools == "base" }
+
+ if originalzero ~= "mtxrun" and originalzero ~= "mtxrun.lua" then
+ arg[0] = specialmapping[originalzero] or originalzero
+ insert(arg,0,"--script")
+ insert(arg,0,"mtxrun")
+ end
+
end
-- environment
@@ -6619,6 +7509,8 @@ local mt = {
setmetatable(environment,mt)
+-- context specific arguments (in order not to confuse the engine)
+
function environment.initializearguments(arg)
local arguments, files = { }, { }
environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
@@ -6627,10 +7519,12 @@ function environment.initializearguments(arg)
if index > 0 then
local flag, value = match(argument,"^%-+(.-)=(.-)$")
if flag then
+ flag = gsub(flag,"^c:","")
arguments[flag] = unquoted(value or "")
else
flag = match(argument,"^%-+(.+)")
if flag then
+ flag = gsub(flag,"^c:","")
arguments[flag] = true
else
files[#files+1] = argument
@@ -6650,7 +7544,7 @@ end
-- tricky: too many hits when we support partials unless we add
-- a registration of arguments so from now on we have 'partial'
-function environment.argument(name,partial)
+function environment.getargument(name,partial)
local arguments, sortedflags = environment.arguments, environment.sortedflags
if arguments[name] then
return arguments[name]
@@ -6673,6 +7567,8 @@ function environment.argument(name,partial)
return nil
end
+environment.argument = environment.getargument
+
function environment.splitarguments(separator) -- rather special, cut-off before separator
local done, before, after = false, { }, { }
local originalarguments = environment.originalarguments
@@ -6758,7 +7654,7 @@ function environment.texfile(filename)
return resolvers.findfile(filename,'tex')
end
-function environment.luafile(filename)
+function environment.luafile(filename) -- needs checking
local resolved = resolvers.findfile(filename,'tex') or ""
if resolved ~= "" then
return resolved
@@ -6770,13 +7666,16 @@ function environment.luafile(filename)
return resolvers.findfile(filename,'luatexlibs') or ""
end
-environment.loadedluacode = loadfile -- can be overloaded
+local function checkstrip(filename)
+ local modu = modules[file.nameonly(filename)]
+ return modu and modu.dataonly
+end
function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format
filename = file.replacesuffix(filename, "lua")
local fullname = environment.luafile(filename)
if fullname and fullname ~= "" then
- local data = environment.loadedluacode(fullname)
+ local data = loadedluacode(fullname,checkstrip,filename)
if trace_locating then
report_lua("loading file %s%s", fullname, not data and " failed" or "")
elseif not silent then
@@ -6874,21 +7773,7 @@ local trace_entities = false trackers.register("xml.entities", function(v) trac
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
---[[ldx--
-<p>The parser used here is inspired by the variant discussed in the lua book, but
-handles comment and processing instructions, has a different structure, provides
-parent access; a first version used different trickery but was less optimized to we
-went this route. First we had a find based parser, now we have an <l n='lpeg'/> based one.
-The find based parser can be found in l-xml-edu.lua along with other older code.</p>
-
-<p>Beware, the interface may change. For instance at, ns, tg, dt may get more
-verbose names. Once the code is stable we will also remove some tracing and
-optimize the code.</p>
-<p>I might even decide to reimplement the parser using the latest <l n='lpeg'/> trickery
-as the current variant was written when <l n='lpeg'/> showed up and it's easier now to
-build tables in one go.</p>
---ldx]]--
xml = xml or { }
local xml = xml
@@ -6898,46 +7783,25 @@ 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, utffind, utfgsub = utf.char, utf.find, utf.gsub
+local utfchar = utf.char
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
---[[ldx--
-<p>First a hack to enable namespace resolving. A namespace is characterized by
-a <l n='url'/>. The following function associates a namespace prefix with a
-pattern. We use <l n='lpeg'/>, which in this case is more than twice as fast as a
-find based solution where we loop over an array of patterns. Less code and
-much cleaner.</p>
---ldx]]--
+
xml.xmlns = xml.xmlns or { }
local check = P(false)
local parse = check
---[[ldx--
-<p>The next function associates a namespace prefix with an <l n='url'/>. This
-normally happens independent of parsing.</p>
-<typing>
-xml.registerns("mml","mathml")
-</typing>
---ldx]]--
function xml.registerns(namespace, pattern) -- pattern can be an lpeg
check = check + C(P(lower(pattern))) / namespace
parse = P { P(check) + 1 * V(1) }
end
---[[ldx--
-<p>The next function also registers a namespace, but this time we map a
-given namespace prefix onto a registered one, using the given
-<l n='url'/>. This used for attributes like <t>xmlns:m</t>.</p>
-<typing>
-xml.checkns("m","http://www.w3.org/mathml")
-</typing>
---ldx]]--
function xml.checkns(namespace,url)
local ns = lpegmatch(parse,lower(url))
@@ -6946,66 +7810,15 @@ function xml.checkns(namespace,url)
end
end
---[[ldx--
-<p>Next we provide a way to turn an <l n='url'/> into a registered
-namespace. This used for the <t>xmlns</t> attribute.</p>
-
-<typing>
-resolvedns = xml.resolvens("http://www.w3.org/mathml")
-</typing>
-This returns <t>mml</t>.
---ldx]]--
function xml.resolvens(url)
return lpegmatch(parse,lower(url)) or ""
end
---[[ldx--
-<p>A namespace in an element can be remapped onto the registered
-one efficiently by using the <t>xml.xmlns</t> table.</p>
---ldx]]--
-
---[[ldx--
-<p>This version uses <l n='lpeg'/>. We follow the same approach as before, stack and top and
-such. This version is about twice as fast which is mostly due to the fact that
-we don't have to prepare the stream for cdata, doctype etc etc. This variant is
-is dedicated to Luigi Scarso, who challenged me with 40 megabyte <l n='xml'/> files that
-took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
-the <l n='lpeg'/> implementation we got that down to less 7.3 seconds. Loading the 14
-<l n='context'/> interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.</p>
-
-<p>Next comes the parser. The rather messy doctype definition comes in many
-disguises so it is no surprice that later on have to dedicate quite some
-<l n='lpeg'/> code to it.</p>
-
-<typing>
-<!DOCTYPE Something PUBLIC "... ..." "..." [ ... ] >
-<!DOCTYPE Something PUBLIC "... ..." "..." >
-<!DOCTYPE Something SYSTEM "... ..." [ ... ] >
-<!DOCTYPE Something SYSTEM "... ..." >
-<!DOCTYPE Something [ ... ] >
-<!DOCTYPE Something >
-</typing>
-
-<p>The code may look a bit complex but this is mostly due to the fact that we
-resolve namespaces and attach metatables. There is only one public function:</p>
-
-<typing>
-local x = xml.convert(somestring)
-</typing>
-
-<p>An optional second boolean argument tells this function not to create a root
-element.</p>
-
-<p>Valid entities are:</p>
-
-<typing>
-<!ENTITY xxxx SYSTEM "yyyy" NDATA zzzz>
-<!ENTITY xxxx PUBLIC "yyyy" >
-<!ENTITY xxxx "yyyy" >
-</typing>
---ldx]]--
+
+
+
-- not just one big nested table capture (lpeg overflow)
@@ -7220,15 +8033,7 @@ 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 escaped = utf.remapper(privates_u)
local function unescaped(s)
local p = privates_n[s]
@@ -7243,13 +8048,7 @@ local function unescaped(s)
return p
end
-local function unprivatized(s,resolve)
- if s == "" then
- return ""
- else
- return (utfgsub(s,".",privates_p))
- end
-end
+local unprivatized = utf.remapper(privates_p)
xml.privatetoken = unescaped
xml.unprivatized = unprivatized
@@ -7589,7 +8388,12 @@ local function _xmlconvert_(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler(format("load error: %s",errorstr))
+ local currentresource = settings.currentresource
+ if currentresource and currentresource ~= "" then
+ xml.errorhandler(format("load error in [%s]: %s",currentresource,errorstr))
+ else
+ xml.errorhandler(format("load error: %s",errorstr))
+ end
end
end
else
@@ -7634,7 +8438,7 @@ function xmlconvert(data,settings)
if ok then
return result
else
- return _xmlconvert_("")
+ return _xmlconvert_("",settings)
end
end
@@ -7655,10 +8459,7 @@ function xml.inheritedconvert(data,xmldata) -- xmldata is parent
return xc
end
---[[ldx--
-<p>Packaging data in an xml like table is done with the following
-function. Maybe it will go away (when not used).</p>
---ldx]]--
+
function xml.is_valid(root)
return root and root.dt and root.dt[1] and type(root.dt[1]) == "table" and not root.dt[1].er
@@ -7677,11 +8478,7 @@ end
xml.errorhandler = report_xml
---[[ldx--
-<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
-the whole file first. The function accepts a string representing
-a filename or a file handle.</p>
---ldx]]--
+
function xml.load(filename,settings)
local data = ""
@@ -7695,13 +8492,17 @@ function xml.load(filename,settings)
elseif filename then -- filehandle
data = filename:read("*all")
end
- return xmlconvert(data,settings)
+ if settings then
+ settings.currentresource = filename
+ local result = xmlconvert(data,settings)
+ settings.currentresource = nil
+ return result
+ else
+ return xmlconvert(data,{ currentresource = filename })
+ end
end
---[[ldx--
-<p>When we inject new elements, we need to convert strings to
-valid trees, which is what the next function does.</p>
---ldx]]--
+
local no_root = { no_root = true }
@@ -7714,11 +8515,7 @@ function xml.toxml(data)
end
end
---[[ldx--
-<p>For copying a tree we use a dedicated function instead of the
-generic table copier. Since we know what we're dealing with we
-can speed up things a bit. The second argument is not to be used!</p>
---ldx]]--
+
local function copy(old,tables)
if old then
@@ -7742,13 +8539,7 @@ end
xml.copy = copy
---[[ldx--
-<p>In <l n='context'/> serializing the tree or parts of the tree is a major
-actitivity which is why the following function is pretty optimized resulting
-in a few more lines of code than needed. The variant that uses the formatting
-function for all components is about 15% slower than the concatinating
-alternative.</p>
---ldx]]--
+
-- todo: add <?xml version='1.0' standalone='yes'?> when not present
@@ -7761,15 +8552,12 @@ function xml.checkbom(root) -- can be made faster
return
end
end
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 1, { special = true, ns = "", tg = "@pi@", dt = { "xml version='1.0' standalone='yes'" } } )
insert(dt, 2, "\n" )
end
end
---[[ldx--
-<p>At the cost of some 25% runtime overhead you can first convert the tree to a string
-and then handle the lot.</p>
---ldx]]--
+
-- new experimental reorganized serialize
@@ -7962,21 +8750,7 @@ newhandlers {
}
}
---[[ldx--
-<p>How you deal with saving data depends on your preferences. For a 40 MB database
-file the timing on a 2.3 Core Duo are as follows (time in seconds):</p>
-
-<lines>
-1.3 : load data from file to string
-6.1 : convert string into tree
-5.3 : saving in file using xmlsave
-6.8 : converting to string using xml.tostring
-3.6 : saving converted string in file
-</lines>
-<p>Beware, these were timing with the old routine but measurements will not be that
-much different I guess.</p>
---ldx]]--
-- maybe this will move to lxml-xml
@@ -8054,10 +8828,7 @@ xml.newhandlers = newhandlers
xml.serialize = serialize
xml.tostring = xmltostring
---[[ldx--
-<p>The next function operated on the content only and needs a handle function
-that accepts a string.</p>
---ldx]]--
+
local function xmlstring(e,handle)
if not handle or (e.special and e.tg ~= "@rt@") then
@@ -8076,9 +8847,7 @@ end
xml.string = xmlstring
---[[ldx--
-<p>A few helpers:</p>
---ldx]]--
+
function xml.settings(e)
@@ -8122,11 +8891,7 @@ function xml.name(root)
end
end
---[[ldx--
-<p>The next helper erases an element but keeps the table as it is,
-and since empty strings are not serialized (effectively) it does
-not harm. Copying the table would take more time. Usage:</p>
---ldx]]--
+
function xml.erase(dt,k)
if dt then
@@ -8138,13 +8903,7 @@ function xml.erase(dt,k)
end
end
---[[ldx--
-<p>The next helper assigns a tree (or string). Usage:</p>
-<typing>
-dt[k] = xml.assign(root) or xml.assign(dt,k,root)
-</typing>
---ldx]]--
function xml.assign(dt,k,root)
if dt and k then
@@ -8157,20 +8916,14 @@ end
-- the following helpers may move
---[[ldx--
-<p>The next helper assigns a tree (or string). Usage:</p>
-<typing>
-xml.tocdata(e)
-xml.tocdata(e,"error")
-</typing>
---ldx]]--
+
function xml.tocdata(e,wrapper) -- a few more in the aux module
local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
- local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e }
+ local t = { special = true, ns = "", tg = "@cd@", at = { }, rn = "", dt = { whatever }, __p__ = e }
setmetatable(t,getmetatable(e))
e.dt = { t }
end
@@ -8225,7 +8978,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['lxml-pth'] = {
+if not modules then modules = { } end modules ['lxml-lpt'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -8246,28 +8999,9 @@ local setmetatableindex = table.setmetatableindex
-- beware, this is not xpath ... e.g. position is different (currently) and
-- we have reverse-sibling as reversed preceding sibling
---[[ldx--
-<p>This module can be used stand alone but also inside <l n='mkiv'/> in
-which case it hooks into the tracker code. Therefore we provide a few
-functions that set the tracers. Here we overload a previously defined
-function.</p>
-<p>If I can get in the mood I will make a variant that is XSLT compliant
-but I wonder if it makes sense.</P>
---ldx]]--
-
---[[ldx--
-<p>Expecially the lpath code is experimental, we will support some of xpath, but
-only things that make sense for us; as compensation it is possible to hook in your
-own functions. Apart from preprocessing content for <l n='context'/> we also need
-this module for process management, like handling <l n='ctx'/> and <l n='rlx'/>
-files.</p>
-
-<typing>
-a/b/c /*/c
-a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
-a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
-</typing>
---ldx]]--
+
+
+
local trace_lpath = false if trackers then trackers.register("xml.path", function(v) trace_lpath = v end) end
local trace_lparse = false if trackers then trackers.register("xml.parse", function(v) trace_lparse = v end) end
@@ -8275,11 +9009,7 @@ local trace_lprofile = false if trackers then trackers.register("xml.profile",
local report_lpath = logs.reporter("xml","lpath")
---[[ldx--
-<p>We've now arrived at an interesting part: accessing the tree using a subset
-of <l n='xpath'/> and since we're not compatible we call it <l n='lpath'/>. We
-will explain more about its usage in other documents.</p>
---ldx]]--
+
local xml = xml
@@ -8731,14 +9461,23 @@ local lp_builtin = P (
-- for the moment we keep namespaces with attributes
local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])")
-local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end)
-local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end)
+
+-- lp_fastpos_p = (P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end
+-- lp_fastpos_n = (P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end
+
+lp_fastpos_p = P("+")^0 * R("09")^1 * P(-1) / "l==%0"
+lp_fastpos_n = P("-") * R("09")^1 * P(-1) / "(%0<0 and (#list+%0==l))"
+
local lp_fastpos = lp_fastpos_n + lp_fastpos_p
+
local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
-local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
- return t .. "("
-end
+-- local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
+-- return t .. "("
+-- end
+
+-- local lp_lua_function = (R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / "%0("
+local lp_lua_function = Cs((R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(")) / "%0"
local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
if expressions[t] then
@@ -9254,9 +9993,7 @@ end
xml.applylpath = applylpath -- takes a table as first argment, which is what xml.filter will do
---[[ldx--
-<p>This is the main filter function. It returns whatever is asked for.</p>
---ldx]]--
+
function xml.filter(root,pattern) -- no longer funny attribute handling here
return applylpath(root,pattern)
@@ -9354,12 +10091,12 @@ xml.selection = selection -- new method, simple handle
-- generic function finalizer (independant namespace)
-local function dofunction(collected,fnc)
+local function dofunction(collected,fnc,...)
if collected then
local f = functions[fnc]
if f then
for c=1,#collected do
- f(collected[c])
+ f(collected[c],...)
end
else
report_lpath("unknown function '%s'",fnc)
@@ -9460,21 +10197,7 @@ expressions.tag = function(e,n) -- only tg
end
end
---[[ldx--
-<p>Often using an iterators looks nicer in the code than passing handler
-functions. The <l n='lua'/> book describes how to use coroutines for that
-purpose (<url href='http://www.lua.org/pil/9.3.html'/>). This permits
-code like:</p>
-<typing>
-for r, d, k in xml.elements(xml.load('text.xml'),"title") do
- print(d[k]) -- old method
-end
-for e in xml.collected(xml.load('text.xml'),"title") do
- print(e) -- new one
-end
-</typing>
---ldx]]--
local wrap, yield = coroutine.wrap, coroutine.yield
@@ -9515,6 +10238,32 @@ function xml.inspect(collection,pattern)
end
end
+-- texy (see xfdf):
+
+local function split(e)
+ local dt = e.dt
+ if dt then
+ for i=1,#dt do
+ local dti = dt[i]
+ if type(dti) == "string" then
+ dti = gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1")
+ dti = gsub(dti,"[\n\r]+","\n\n")
+ dt[i] = dti
+ else
+ split(dti)
+ end
+ end
+ end
+ return e
+end
+
+function xml.finalizers.paragraphs(c)
+ for i=1,#c do
+ split(c[i])
+ end
+ return c
+end
+
end -- of closure
@@ -9539,13 +10288,7 @@ local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, l
lpegpatterns.xml = lpegpatterns.xml or { }
local xmlpatterns = lpegpatterns.xml
---[[ldx--
-<p>The following helper functions best belong to the <t>lxml-ini</t>
-module. Some are here because we need then in the <t>mk</t>
-document and other manuals, others came up when playing with
-this module. Since this module is also used in <l n='mtxrun'/> we've
-put them here instead of loading mode modules there then needed.</p>
---ldx]]--
+
local function xmlgsub(t,old,new) -- will be replaced
local dt = t.dt
@@ -9731,9 +10474,7 @@ function xml.processattributes(root,pattern,handle)
return collected
end
---[[ldx--
-<p>The following functions collect elements and texts.</p>
---ldx]]--
+
-- are these still needed -> lxml-cmp.lua
@@ -9772,9 +10513,7 @@ function xml.collect_tags(root, pattern, nonamespace)
end
end
---[[ldx--
-<p>We've now arrived at the functions that manipulate the tree.</p>
---ldx]]--
+
local no_root = { no_root = true }
@@ -10160,9 +10899,7 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
end
---[[ldx--
-<p>Helper (for q2p).</p>
---ldx]]--
+
function xml.cdatatotext(e)
local dt = e.dt
@@ -10259,9 +10996,7 @@ end
-- xml.addentitiesdoctype(x,"hexadecimal")
-- print(x)
---[[ldx--
-<p>Here are a few synonyms.</p>
---ldx]]--
+
xml.all = xml.each
xml.insert = xml.insertafter
@@ -10852,7 +11587,7 @@ local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string
local concat = table.concat
local next, type = next, type
-local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
+local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
@@ -11202,12 +11937,14 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
for s in gmatch(str,"[^,]+") do
s = validate(s)
if s then
- n = n + 1 ; t[n] = s
+ n = n + 1
+ t[n] = s
end
end
else
for s in gmatch(str,"[^,]+") do
- n = n + 1 ; t[n] = s
+ n = n + 1
+ t[n] = s
end
end
if trace_expansions then
@@ -11221,7 +11958,7 @@ end
-- We could make the previous one public.
local function validate(s)
- s = collapsepath(s) -- already keeps the //
+ s = collapsepath(s) -- already keeps the trailing / and //
return s ~= "" and not find(s,"^!*unset/*$") and s
end
@@ -11559,7 +12296,7 @@ local resolvers = resolvers
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
-local fileextname = file.extname
+local suffixonly = file.suffixonly
local formats = allocate()
local suffixes = allocate()
@@ -11814,7 +12551,7 @@ function resolvers.formatofvariable(str)
end
function resolvers.formatofsuffix(str) -- of file
- return suffixmap[fileextname(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
+ return suffixmap[suffixonly(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
end
function resolvers.variableofformat(str)
@@ -11826,7 +12563,7 @@ function resolvers.variableofformatorsuffix(str)
if v then
return v
end
- v = suffixmap[fileextname(str)]
+ v = suffixmap[suffixonly(str)]
if v then
return formats[v]
end
@@ -11847,21 +12584,7 @@ if not modules then modules = { } end modules ['data-tmp'] = {
license = "see context related readme files"
}
---[[ldx--
-<p>This module deals with caching data. It sets up the paths and
-implements loaders and savers for tables. Best is to set the
-following variable. When not set, the usual paths will be
-checked. Personally I prefer the (users) temporary path.</p>
-
-</code>
-TEXMFCACHE=$TMP;$TEMP;$TMPDIR;$TEMPDIR;$HOME;$TEXMFVAR;$VARTEXMF;.
-</code>
-<p>Currently we do no locking when we write files. This is no real
-problem because most caching involves fonts and the chance of them
-being written at the same time is small. We also need to extend
-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
@@ -12396,11 +13119,12 @@ local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local filedirname = file.dirname
local filebasename = file.basename
-local fileextname = file.extname
+local suffixonly = file.suffixonly
local filejoin = file.join
local collapsepath = file.collapsepath
local joinpath = file.joinpath
local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -12424,7 +13148,7 @@ resolvers.cacheversion = '1.0.1'
resolvers.configbanner = ''
resolvers.homedir = environment.homedir
resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" }
-resolvers.luacnfname = 'texmfcnf.lua'
+resolvers.luacnfname = "texmfcnf.lua"
resolvers.luacnfstate = "unknown"
-- The web2c tex binaries as well as kpse have built in paths for the configuration
@@ -12696,7 +13420,7 @@ end
local function identify_configuration_files()
local specification = instance.specification
if #specification == 0 then
- local cnfspec = getenv('TEXMFCNF')
+ local cnfspec = getenv("TEXMFCNF")
if cnfspec == "" then
cnfspec = resolvers.luacnfspec
resolvers.luacnfstate = "default"
@@ -12784,7 +13508,7 @@ local function load_configuration_files()
-- we push the value into the main environment (osenv) so
-- that it takes precedence over the default one and therefore
-- also over following definitions
- resolvers.setenv('TEXMFCNF',cnfspec) -- resolves prefixes
+ resolvers.setenv("TEXMFCNF",cnfspec) -- resolves prefixes
-- we now identify and load the specified configuration files
instance.specification = { }
identify_configuration_files()
@@ -12832,10 +13556,11 @@ end
local function locate_file_databases()
-- todo: cache:// and tree:// (runtime)
- local texmfpaths = resolvers.expandedpathlist('TEXMF')
+ local texmfpaths = resolvers.expandedpathlist("TEXMF")
if #texmfpaths > 0 then
for i=1,#texmfpaths do
local path = collapsepath(texmfpaths[i])
+ path = gsub(path,"/+$","") -- in case $HOME expands to something with a trailing /
local stripped = lpegmatch(inhibitstripper,path) -- the !! thing
if stripped ~= "" then
local runtime = stripped == path
@@ -12964,9 +13689,9 @@ function resolvers.prependhash(type,name,cache)
end
function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash
- local t = resolvers.splitpath(getenv('TEXMF'))
+ local t = resolvers.splitpath(getenv("TEXMF")) -- okay?
insert(t,1,specification)
- local newspec = concat(t,";")
+ local newspec = concat(t,",") -- not ;
if instance.environment["TEXMF"] then
instance.environment["TEXMF"] = newspec
elseif instance.variables["TEXMF"] then
@@ -13041,14 +13766,19 @@ function resolvers.resetextrapath()
end
function resolvers.registerextrapath(paths,subpaths)
+ paths = settings_to_array(paths)
+ subpaths = settings_to_array(subpaths)
local ep = instance.extra_paths or { }
local oldn = #ep
local newn = oldn
- if paths and paths ~= "" then
- if subpaths and subpaths ~= "" then
- for p in gmatch(paths,"[^,]+") do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
+ local nofpaths = #paths
+ local nofsubpaths = #subpaths
+ if nofpaths > 0 then
+ if nofsubpaths > 0 then
+ for i=1,nofpaths do
+ local p = paths[i]
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
local ps = p .. "/" .. s
if not done[ps] then
newn = newn + 1
@@ -13058,7 +13788,8 @@ function resolvers.registerextrapath(paths,subpaths)
end
end
else
- for p in gmatch(paths,"[^,]+") do
+ for i=1,nofpaths do
+ local p = paths[i]
if not done[p] then
newn = newn + 1
ep[newn] = resolvers.cleanpath(p)
@@ -13066,10 +13797,10 @@ function resolvers.registerextrapath(paths,subpaths)
end
end
end
- elseif subpaths and subpaths ~= "" then
+ elseif nofsubpaths > 0 then
for i=1,oldn do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
local ps = ep[i] .. "/" .. s
if not done[ps] then
newn = newn + 1
@@ -13147,18 +13878,21 @@ function resolvers.expandedpathlist(str)
return { }
elseif instance.savelists then
str = lpegmatch(dollarstripper,str)
- if not instance.lists[str] then -- cached
- local lst = made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
- instance.lists[str] = expandedpathfromlist(lst)
- end
- return instance.lists[str]
+ local lists = instance.lists
+ local lst = lists[str]
+ if not lst then
+ local l = made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ lst = expandedpathfromlist(l)
+ lists[str] = lst
+ end
+ return lst
else
local lst = resolvers.splitpath(resolvers.expansion(str))
return made_list(instance,expandedpathfromlist(lst))
end
end
-function resolvers.expandedpathlistfromvariable(str) -- brrr
+function resolvers.expandedpathlistfromvariable(str) -- brrr / could also have cleaner ^!! /$ //
str = lpegmatch(dollarstripper,str)
local tmp = resolvers.variableofformatorsuffix(str)
return resolvers.expandedpathlist(tmp ~= "" and tmp or str)
@@ -13315,7 +14049,7 @@ local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
local collect_instance_files
local function find_analyze(filename,askedformat,allresults)
- local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ local filetype, wantedfiles, ext = '', { }, suffixonly(filename)
-- too tricky as filename can be bla.1.2.3:
--
-- if not suffixmap[ext] then
@@ -13393,7 +14127,7 @@ local function find_qualified(filename,allresults) -- this one will be split too
if trace_detail then
report_resolving("locating qualified file '%s'", filename)
end
- local forcedname, suffix = "", fileextname(filename)
+ local forcedname, suffix = "", suffixonly(filename)
if suffix == "" then -- why
local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
if format_suffixes then
@@ -14063,6 +14797,8 @@ local gsub = string.gsub
local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+local joinpath, basename, dirname = file.join, file.basename, file.dirname
+local getmetatable, rawset, type = getmetatable, rawset, type
-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
@@ -14104,28 +14840,43 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
+ return cleanpath(basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.dirname((fullname ~= "" and fullname) or str))
+ return cleanpath(dirname((fullname ~= "" and fullname) or str))
end
prefixes.selfautoloc = function(str)
- return cleanpath(file.join(getenv('SELFAUTOLOC'),str))
+ return cleanpath(joinpath(getenv('SELFAUTOLOC'),str))
end
prefixes.selfautoparent = function(str)
- return cleanpath(file.join(getenv('SELFAUTOPARENT'),str))
+ return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str))
end
prefixes.selfautodir = function(str)
- return cleanpath(file.join(getenv('SELFAUTODIR'),str))
+ return cleanpath(joinpath(getenv('SELFAUTODIR'),str))
end
prefixes.home = function(str)
- return cleanpath(file.join(getenv('HOME'),str))
+ return cleanpath(joinpath(getenv('HOME'),str))
+end
+
+local function toppath()
+ local pathname = dirname(inputstack[#inputstack] or "")
+ if pathname == "" then
+ return "."
+ else
+ return pathname
+ end
+end
+
+resolvers.toppath = toppath
+
+prefixes.toppath = function(str)
+ return cleanpath(joinpath(toppath(),str))
end
prefixes.env = prefixes.environment
@@ -14161,6 +14912,8 @@ function resolvers.resetresolve(str)
resolved, abstract = { }, { }
end
+-- todo: use an lpeg (see data-lua for !! / stripper)
+
local function resolve(str) -- use schemes, this one is then for the commandline only
if type(str) == "table" then
local t = { }
@@ -14186,7 +14939,7 @@ end
resolvers.resolve = resolve
resolvers.unresolve = unresolve
-if os.uname then
+if type(os.uname) == "function" then
for k, v in next, os.uname() do
if not prefixes[k] then
@@ -14198,11 +14951,17 @@ end
if os.type == "unix" then
+ -- We need to distringuish between a prefix and something else : so we
+ -- have a special repath variant for linux. Also, when a new prefix is
+ -- defined, we need to remake the matcher.
+
local pattern
local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
local colon = P(":")
- local p
for k, v in table.sortedpairs(prefixes) do
if p then
p = P(k) + p
@@ -14211,9 +14970,6 @@ if os.type == "unix" then
end
end
pattern = Cs((p * colon + colon/";" + P(1))^0)
- if t then
- t[k] = v
- end
end
makepattern()
@@ -14424,18 +15180,7 @@ local trace_cache = false trackers.register("resolvers.cache", functi
local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
---[[ldx--
-<p>Once we found ourselves defining similar cache constructs
-several times, containers were introduced. Containers are used
-to collect tables in memory and reuse them when possible based
-on (unique) hashes (to be provided by the calling function).</p>
-
-<p>Caching to disk is disabled by default. Version numbers are
-stored in the saved table which makes it possible to change the
-table structures without bothering about the disk cache.</p>
-<p>Examples of usage can be found in the font related code.</p>
---ldx]]--
containers = containers or { }
local containers = containers
@@ -14670,11 +15415,7 @@ local trace_locating = false trackers.register("resolvers.locating", function(v
local report_zip = logs.reporter("resolvers","zip")
--- zip:///oeps.zip?name=bla/bla.tex
--- zip:///oeps.zip?tree=tex/texmf-local
--- zip:///texmf.zip?tree=/tex/texmf
--- zip:///texmf.zip?tree=/tex/texmf-local
--- zip:///texmf-mine.zip?tree=/tex/texmf-projects
+
local resolvers = resolvers
@@ -14999,7 +15740,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-crl'] = {
+if not modules then modules = { } end modules ['data-sch'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -15007,60 +15748,199 @@ if not modules then modules = { } end modules ['data-crl'] = {
license = "see context related readme files"
}
--- this one is replaced by data-sch.lua --
+local loadstring = loadstring
+local gsub, concat, format = string.gsub, table.concat, string.format
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
-local gsub = string.gsub
+local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end)
+local report_schemes = logs.reporter("resolvers","schemes")
-local resolvers = resolvers
+local http = require("socket.http")
+local ltn12 = require("ltn12")
-local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+local resolvers = resolvers
+local schemes = resolvers.schemes or { }
+resolvers.schemes = schemes
+
+local cleaners = { }
+schemes.cleaners = cleaners
+
+local threshold = 24 * 60 * 60
+
+directives.register("schemes.threshold", function(v) threshold = tonumber(v) or threshold end)
+
+function cleaners.none(specification)
+ return specification.original
+end
+
+function cleaners.strip(specification)
+ return (gsub(specification.original,"[^%a%d%.]+","-")) -- so we keep periods
+end
+
+function cleaners.md5(specification)
+ return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
+end
+
+local cleaner = cleaners.strip
+
+directives.register("schemes.cleanmethod", function(v) cleaner = cleaners[v] or cleaners.strip end)
+
+function resolvers.schemes.cleanname(specification)
+ local hash = cleaner(specification)
+ if trace_schemes then
+ report_schemes("hashing %s to %s",specification.original,hash)
+ end
+ return hash
+end
-resolvers.curl = resolvers.curl or { }
-local curl = resolvers.curl
+local cached, loaded, reused, thresholds, handlers = { }, { }, { }, { }, { }
-local cached = { }
+local function runcurl(name,cachename) -- we use sockets instead or the curl library when possible
+ local command = "curl --silent --create-dirs --output " .. cachename .. " " .. name
+ os.spawn(command)
+end
-local function runcurl(specification)
+local function fetch(specification)
local original = specification.original
- -- local scheme = specification.scheme
- local cleanname = gsub(original,"[^%a%d%.]+","-")
- local cachename = caches.setfirstwritablefile(cleanname,"curl")
+ local scheme = specification.scheme
+ local cleanname = schemes.cleanname(specification)
+ local cachename = caches.setfirstwritablefile(cleanname,"schemes")
if not cached[original] then
- if not io.exists(cachename) then
+ statistics.starttiming(schemes)
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > (thresholds[protocol] or threshold)) then
cached[original] = cachename
- local command = "curl --silent --create-dirs --output " .. cachename .. " " .. original
- os.spawn(command)
+ local handler = handlers[scheme]
+ if handler then
+ if trace_schemes then
+ report_schemes("fetching '%s', protocol '%s', method 'built-in'",original,scheme)
+ end
+ logs.flush()
+ handler(specification,cachename)
+ else
+ if trace_schemes then
+ report_schemes("fetching '%s', protocol '%s', method 'curl'",original,scheme)
+ end
+ logs.flush()
+ runcurl(original,cachename)
+ end
end
if io.exists(cachename) then
cached[original] = cachename
+ if trace_schemes then
+ report_schemes("using cached '%s', protocol '%s', cachename '%s'",original,scheme,cachename)
+ end
else
cached[original] = ""
+ if trace_schemes then
+ report_schemes("using missing '%s', protocol '%s'",original,scheme)
+ end
+ end
+ loaded[scheme] = loaded[scheme] + 1
+ statistics.stoptiming(schemes)
+ else
+ if trace_schemes then
+ report_schemes("reusing '%s', protocol '%s'",original,scheme)
end
+ reused[scheme] = reused[scheme] + 1
end
return cached[original]
end
--- old code: we could be cleaner using specification (see schemes)
-
local function finder(specification,filetype)
- return resolvers.methodhandler("finders",runcurl(specification),filetype)
+ return resolvers.methodhandler("finders",fetch(specification),filetype)
end
local opener = openers.file
local loader = loaders.file
-local function install(scheme)
- finders[scheme] = finder
- openers[scheme] = opener
- loaders[scheme] = loader
+local function install(scheme,handler,newthreshold)
+ handlers [scheme] = handler
+ loaded [scheme] = 0
+ reused [scheme] = 0
+ finders [scheme] = finder
+ openers [scheme] = opener
+ loaders [scheme] = loader
+ thresholds[scheme] = newthreshold or threshold
end
-resolvers.curl.install = install
+schemes.install = install
+
+local function http_handler(specification,cachename)
+ local tempname = cachename .. ".tmp"
+ local f = io.open(tempname,"wb")
+ local status, message = http.request {
+ url = specification.original,
+ sink = ltn12.sink.file(f)
+ }
+ if not status then
+ os.remove(tempname)
+ else
+ os.remove(cachename)
+ os.rename(tempname,cachename)
+ end
+ return cachename
+end
-install('http')
-install('https')
+install('http',http_handler)
+install('https') -- see pod
install('ftp')
+statistics.register("scheme handling time", function()
+ local l, r, nl, nr = { }, { }, 0, 0
+ for k, v in table.sortedhash(loaded) do
+ if v > 0 then
+ nl = nl + 1
+ l[nl] = k .. ":" .. v
+ end
+ end
+ for k, v in table.sortedhash(reused) do
+ if v > 0 then
+ nr = nr + 1
+ r[nr] = k .. ":" .. v
+ end
+ end
+ local n = nl + nr
+ if n > 0 then
+ l = nl > 0 and concat(l) or "none"
+ r = nr > 0 and concat(r) or "none"
+ return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
+ statistics.elapsedtime(schemes), n, threshold, l, r)
+ else
+ return nil
+ end
+end)
+
+-- We provide a few more helpers:
+
+----- http = require("socket.http")
+local httprequest = http.request
+local toquery = url.toquery
+
+-- local function httprequest(url)
+-- return os.resultof(format("curl --silent %q", url))
+-- end
+
+local function fetchstring(url,data)
+ local q = data and toquery(data)
+ if q then
+ url = url .. "?" .. q
+ end
+ local reply = httprequest(url)
+ return reply -- just one argument
+end
+
+schemes.fetchstring = fetchstring
+
+function schemes.fetchtable(url,data)
+ local reply = fetchstring(url,data)
+ if reply then
+ local s = loadstring("return " .. reply)
+ if s then
+ return s()
+ end
+ end
+end
+
end -- of closure
@@ -15074,170 +15954,199 @@ if not modules then modules = { } end modules ['data-lua'] = {
license = "see context related readme files"
}
--- some loading stuff ... we might move this one to slot 2 depending
--- on the developments (the loaders must not trigger kpse); we could
--- of course use a more extensive lib path spec
+-- We overload the regular loader. We do so because we operate mostly in
+-- tds and use our own loader code. Alternatively we could use a more
+-- extensive definition of package.path and package.cpath but even then
+-- we're not done. Also, we now have better tracing.
+--
+-- -- local mylib = require("libtest")
+-- -- local mysql = require("luasql.mysql")
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local concat = table.concat
+
+local trace_libraries = false
+
+trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+trackers.register("resolvers.locating", function(v) trace_libraries = v end)
local report_libraries = logs.reporter("resolvers","libraries")
local gsub, insert = string.gsub, table.insert
+local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
local unpack = unpack or table.unpack
+local is_readable = file.is_readable
local resolvers, package = resolvers, package
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
-local clibformats = { 'lib' }
-
-local _path_, libpaths, _cpath_, clibpaths
-
-function package.libpaths()
- if not _path_ or package.path ~= _path_ then
- _path_ = package.path
- libpaths = file.splitpath(_path_,";")
+local libsuffixes = { 'tex', 'lua' }
+local clibsuffixes = { 'lib' }
+local libformats = { 'TEXINPUTS', 'LUAINPUTS' }
+local clibformats = { 'CLUAINPUTS' }
+
+local libpaths = nil
+local clibpaths = nil
+local libhash = { }
+local clibhash = { }
+local libextras = { }
+local clibextras = { }
+
+local pattern = Cs(P("!")^0 / "" * (P("/") * P(-1) / "/" + P("/")^1 / "/" + 1)^0)
+
+local function cleanpath(path) --hm, don't we have a helper for this?
+ return resolvers.resolve(lpegmatch(pattern,path))
+end
+
+local function getlibpaths()
+ if not libpaths then
+ libpaths = { }
+ for i=1,#libformats do
+ local paths = resolvers.expandedpathlistfromvariable(libformats[i])
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not libhash[path] then
+ libpaths[#libpaths+1] = path
+ libhash[path] = true
+ end
+ end
+ end
end
return libpaths
end
-function package.clibpaths()
- if not _cpath_ or package.cpath ~= _cpath_ then
- _cpath_ = package.cpath
- clibpaths = file.splitpath(_cpath_,";")
+local function getclibpaths()
+ if not clibpaths then
+ clibpaths = { }
+ for i=1,#clibformats do
+ local paths = resolvers.expandedpathlistfromvariable(clibformats[i])
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not clibhash[path] then
+ clibpaths[#clibpaths+1] = path
+ clibhash[path] = true
+ end
+ end
+ end
end
return clibpaths
end
-local function thepath(...)
- local t = { ... } t[#t+1] = "?.lua"
- local path = file.join(unpack(t))
- if trace_locating then
- report_libraries("! appending '%s' to 'package.path'",path)
+package.libpaths = getlibpaths
+package.clibpaths = getclibpaths
+
+function package.extralibpath(...)
+ local paths = { ... }
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not libhash[path] then
+ if trace_libraries then
+ report_libraries("! extra lua path '%s'",path)
+ end
+ libextras[#libextras+1] = path
+ libpaths[#libpaths +1] = path
+ end
end
- return path
end
-local p_libpaths, a_libpaths = { }, { }
-
-function package.appendtolibpath(...)
- insert(a_libpath,thepath(...))
+function package.extraclibpath(...)
+ local paths = { ... }
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not clibhash[path] then
+ if trace_libraries then
+ report_libraries("! extra lib path '%s'",path)
+ end
+ clibextras[#clibextras+1] = path
+ clibpaths[#clibpaths +1] = path
+ end
+ end
end
-function package.prependtolibpath(...)
- insert(p_libpaths,1,thepath(...))
+if not package.loaders[-2] then
+ -- use package-path and package-cpath
+ package.loaders[-2] = package.loaders[2]
end
--- beware, we need to return a loadfile result !
+local function loadedaslib(resolved,rawname)
+ return package.loadlib(resolved,"luaopen_" .. gsub(rawname,"%.","_"))
+end
-local function loaded(libpaths,name,simple)
- for i=1,#libpaths do -- package.path, might become option
- local libpath = libpaths[i]
- local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
+local function loadedbylua(name)
+ if trace_libraries then
+ report_libraries("! locating %q using normal loader",name)
end
+ local resolved = package.loaders[-2](name)
end
-package.loaders[2] = function(name) -- was [#package.loaders+1]
- 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
+local function loadedbyformat(name,rawname,suffixes,islib)
+ if trace_libraries then
+ report_libraries("! locating %q as %q using formats %q",rawname,name,concat(suffixes))
end
- for i=1,#libformats do
- local format = libformats[i]
+ for i=1,#suffixes do -- so we use findfile and not a lookup loop
+ local format = suffixes[i]
local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
+ if trace_libraries then
+ report_libraries("! checking for %q' using format %q",name,format)
end
if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
+ if trace_libraries then
+ report_libraries("! lib %q located on %q",name,resolved)
end
- return loadfile(resolved)
- end
- end
- -- libpaths
- local libpaths, clibpaths = package.libpaths(), package.clibpaths()
- local simple = gsub(name,"%.lua$","")
- local simple = gsub(simple,"%.","/")
- local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple)
- if resolved then
- return resolved
- end
- --
- local libname = file.addsuffix(simple,os.libsuffix)
- for i=1,#clibformats do
- -- better have a dedicated loop
- local format = clibformats[i]
- local paths = resolvers.expandedpathlistfromvariable(format)
- for p=1,#paths do
- local path = paths[p]
- local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
- end
- return package.loadlib(resolved,name)
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
end
end
end
- for i=1,#clibpaths do -- package.path, might become option
- local libpath = clibpaths[i]
- local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
+end
+
+local function loadedbypath(name,rawname,paths,islib,what)
+ if trace_libraries then
+ report_libraries("! locating %q as %q on %q paths",rawname,name,what)
+ end
+ for p=1,#paths do
+ local path = paths[p]
+ local resolved = file.join(path,name)
+ if trace_libraries then -- mode detail
+ report_libraries("! checking for %q using %q path %q",name,what,path)
end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
+ if is_readable(resolved) then
+ if trace_libraries then
+ report_libraries("! lib %q located on %q",name,resolved)
+ end
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
end
- return package.loadlib(resolved,name)
- end
- end
- -- just in case the distribution is messed up
- if trace_loading then -- more detail
- report_libraries("! checking for '%s' using 'luatexlibs': '%s'",name)
- end
- local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
- if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
end
- return loadfile(resolved)
- end
- if trace_locating then
- report_libraries('? unable to locate lib: %s',name)
end
--- return "unable to locate " .. name
end
-resolvers.loadlualib = require
-
--- -- -- --
+local function notloaded(name)
+ if trace_libraries then
+ report_libraries("? unable to locate library %q",name)
+ end
+end
-package.obsolete = package.obsolete or { }
+package.loaders[2] = function(name)
+ local thename = gsub(name,"%.","/")
+ local luaname = file.addsuffix(thename,"lua")
+ local libname = file.addsuffix(thename,os.libsuffix)
+ return
+ loadedbyformat(luaname,name,libsuffixes, false)
+ or loadedbyformat(libname,name,clibsuffixes, true)
+ or loadedbypath (luaname,name,getlibpaths (),false,"lua")
+ or loadedbypath (luaname,name,getclibpaths(),false,"lua")
+ or loadedbypath (libname,name,getclibpaths(),true, "lib")
+ or loadedbylua (name)
+ or notloaded (name)
+end
-package.append_libpath = appendtolibpath -- will become obsolete
-package.prepend_libpath = prependtolibpath -- will become obsolete
+-- package.loaders[3] = nil
+-- package.loaders[4] = nil
-package.obsolete.append_libpath = appendtolibpath -- will become obsolete
-package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+resolvers.loadlualib = require
end -- of closure
@@ -15707,7 +16616,6 @@ function environment.make_format(name)
end
function environment.run_format(name,data,more)
- -- hm, rather old code here; we can now use the file.whatever functions
if name and name ~= "" then
local barename = file.removesuffix(name)
local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
@@ -15737,6 +16645,129 @@ end
end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['util-tpl'] = {
+ 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"
+}
+
+-- This is experimental code. Coming from dos and windows, I've always used %whatever%
+-- as template variables so let's stick to it. After all, it's easy to parse and stands
+-- out well. A double %% is turned into a regular %.
+
+utilities.templates = utilities.templates or { }
+local templates = utilities.templates
+
+local trace_template = false trackers.register("templates.trace",function(v) trace_template = v end)
+local report_template = logs.reporter("template")
+
+local format = string.format
+local P, C, Cs, Carg, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.Carg, lpeg.match
+
+-- todo: make installable template.new
+
+local replacer
+
+local function replacekey(k,t,recursive)
+ local v = t[k]
+ if not v then
+ if trace_template then
+ report_template("unknown key %q",k)
+ end
+ return ""
+ else
+ if trace_template then
+ report_template("setting key %q to value %q",k,v)
+ end
+ if recursive then
+ return lpegmatch(replacer,v,1,t)
+ else
+ return v
+ end
+ end
+end
+
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local escapers = {
+ lua = function(s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local function replacekeyunquoted(s,t,how,recurse) -- ".. \" "
+ local escaper = how and escapers[how] or escapers.lua
+ return escaper(replacekey(s,t,recurse))
+end
+
+local single = P("%") -- test %test% test : resolves test
+local double = P("%%") -- test 10%% test : %% becomes %
+local lquoted = P("%[") -- test %[test]" test : resolves test with escaped "'s
+local rquoted = P("]%") --
+
+local escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
+
+local key = nosingle * (C((1-nosingle)^1 * Carg(1) * Carg(2) * Carg(3))/replacekey) * nosingle
+local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2) * Carg(3))/replacekeyunquoted) * norquoted
+local any = P(1)
+
+ replacer = Cs((unquoted + escape + key + any)^0)
+
+local function replace(str,mapping,how,recurse)
+ if mapping then
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+ return str
+ end
+end
+
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] },'sql'))
+
+templates.replace = replace
+
+function templates.load(filename,mapping,how,recurse)
+ local data = io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+ return replace(data,mapping,how,recurse)
+ else
+ return data
+ end
+end
+
+function templates.resolve(t,mapping,how,recurse)
+ if not mapping then
+ mapping = t
+ end
+ for k, v in next, t do
+ t[k] = replace(v,mapping,how,recurse)
+ end
+ return t
+end
+
+-- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" }))
+-- inspect(utilities.templates.resolve({ one = "%two%", two = "two", three = "%three%" }))
+
+
+end -- of closure
-- end library merge
own = { } -- not local, might change
@@ -15796,7 +16827,7 @@ own.libs = { -- order can be made better
-- 'data-bin.lua',
'data-zip.lua',
'data-tre.lua',
- 'data-crl.lua',
+ 'data-sch.lua',
'data-lua.lua',
'data-aux.lua', -- updater
'data-tmf.lua',
@@ -15804,6 +16835,8 @@ own.libs = { -- order can be made better
'luat-sta.lua',
'luat-fmt.lua',
+
+ 'util-tpl.lua',
}
-- We need this hack till luatex is fixed.
@@ -15824,7 +16857,7 @@ own.path = gsub(match(own.name,"^(.+)[\\/].-$") or ".","\\","/")
local ownpath, owntree = own.path, environment and environment.ownpath or own.path
-own.list = {
+own.list = { -- predictable paths
'.',
ownpath ,
ownpath .. "/../sources", -- HH's development path
@@ -15848,7 +16881,7 @@ local function locate_libs()
local filename = pth .. "/" .. lib
local found = lfs.isfile(filename)
if found then
- package.path = package.path .. ";" .. pth .. "/?.lua" -- in case l-* does a require
+ package.path = package.path .. ";" .. pth .. "/?.lua" -- in case l-* does a require (probably obsolete)
return pth
end
end
@@ -15980,6 +17013,7 @@ local helpinfo = [[
--var-value report value of variable
--find-file report file location
--find-path report path of file
+--show-package-path report package paths
--pattern=str filter variables
]]
@@ -16093,7 +17127,8 @@ function runners.execute_script(fullname,internal,nosplit)
elseif state == 'skip' then
return true
elseif state == "run" then
- local path, name, suffix, result = file.dirname(fullname), file.basename(fullname), file.extname(fullname), ""
+ local path, name, suffix = file.splitname(fullname)
+ local result = ""
if path ~= "" then
result = fullname
elseif name then
@@ -16104,7 +17139,7 @@ function runners.execute_script(fullname,internal,nosplit)
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)
+ suffix = file.suffix(name)
end
if suffix == "" then
-- loop over known suffixes
@@ -16131,7 +17166,7 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local binary = runners.applications[file.extname(result)]
+ local binary = runners.applications[file.suffix(result)]
result = string.quoted(string.unquoted(result))
-- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
-- result = '"' .. result .. '"'
@@ -16324,7 +17359,7 @@ function resolvers.launch(str)
-- maybe we also need to test on mtxrun.launcher.suffix environment
-- variable or on windows consult the assoc and ftype vars and such
local launchers = runners.launchers[os.platform] if launchers then
- local suffix = file.extname(str) if suffix then
+ local suffix = file.suffix(str) if suffix then
local runner = launchers[suffix] if runner then
str = runner .. " " .. str
end
@@ -16383,7 +17418,7 @@ function runners.find_mtx_script(filename)
end
filename = file.addsuffix(filename,"lua")
local basename = file.removesuffix(file.basename(filename))
- local suffix = file.extname(filename)
+ local suffix = file.suffix(filename)
-- qualified path, raw name
local fullname = file.is_qualified_path(filename) and io.exists(filename) and filename
if fullname and fullname ~= "" then
@@ -16438,7 +17473,7 @@ function runners.execute_ctx_script(filename,...)
runners.register_arguments(...)
local arguments = environment.arguments_after
local fullname = runners.find_mtx_script(filename) or ""
- if file.extname(fullname) == "cld" then
+ if file.suffix(fullname) == "cld" then
-- handy in editors where we force --autopdf
report("running cld script: %s",filename)
table.insert(arguments,1,fullname)
@@ -16546,6 +17581,21 @@ function runners.timed(action)
statistics.timed(action)
end
+function runners.associate(filename)
+ os.launch(filename)
+end
+
+function runners.gethelp(filename)
+ local url = environment.argument("url")
+ if url and url ~= "" then
+ local command = string.gsub(environment.argument("command") or "unknown","^%s*\\*(.-)%s*$","%1")
+ url = utilities.templates.replace(url,{ command = command })
+ os.launch(url)
+ else
+ report("no --url given")
+ end
+end
+
-- this is a bit dirty ... first we store the first filename and next we
-- split the arguments so that we only see the ones meant for this script
-- ... later we will use the second half
@@ -16648,7 +17698,18 @@ else
end
-if e_argument("selfmerge") then
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
+
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
+
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -16671,23 +17732,25 @@ elseif e_argument("selfupdate") then
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif e_argument("ctxlua") or e_argument("internal") then
+elseif e_argument("show-package-path") or e_argument("show-package-paths") then
- -- run a script by loading it (using libs)
+ local l = package.libpaths()
+ local c = package.clibpaths()
- runners.loadbase()
- ok = runners.execute_script(filename,true)
+ for i=1,#l do
+ report("package lib path %s: %s",i,l[i])
+ end
-elseif e_argument("script") or e_argument("scripts") then
+ for i=1,#c do
+ report("package clib path %s: %s",i,c[i])
+ end
- -- run a script by loading it (using libs), pass args
+elseif e_argument("ctxlua") or e_argument("internal") then
+
+ -- run a script by loading it (using libs)
runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
+ ok = runners.execute_script(filename,true)
elseif e_argument("execute") then
@@ -16715,6 +17778,14 @@ elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
+elseif e_argument("associate") then
+
+ runners.associate(filename)
+
+elseif e_argument("gethelp") then
+
+ runners.gethelp()
+
elseif e_argument("makestubs") then
-- make stubs (depricated)
@@ -16806,7 +17877,7 @@ elseif e_argument("find-path") then
elseif e_argument("expand-braces") then
- -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename
+ -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
resolvers.load("nofiles")
runners.register_arguments(filename)
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index 108f2a8a1..e6bbbe2b5 100644
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -8,6 +8,11 @@ if not modules then modules = { } end modules ['mtxrun'] = {
license = "see context related readme files"
}
+-- if not lpeg then require("lpeg") end
+-- if not md5 then require("md5") end
+-- if not lfs then require("lfs") end
+-- if not texconfig then texconfig = { } end
+
-- one can make a stub:
--
-- #!/bin/sh
@@ -150,11 +155,28 @@ function string.topattern(str,lowercase,strict)
end
end
+
+function string.valid(str,default)
+ return (type(str) == "string" and str ~= "" and str) or default or nil
+end
+
-- obsolete names:
string.quote = string.quoted
string.unquote = string.unquoted
+-- handy fallback
+
+string.itself = function(s) return s end
+
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -168,7 +190,8 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string
+local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local table, string = table, string
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
@@ -179,6 +202,8 @@ local getinfo = debug.getinfo
-- impact on ConTeXt was not that large; the remaining ipairs already
-- have been replaced. In a similar fashion we also hardly used pairs.
--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -238,12 +263,16 @@ function table.strip(tab)
end
function table.keys(t)
- local keys, k = { }, 0
- for key, _ in next, t do
- k = k + 1
- keys[k] = key
+ if t then
+ local keys, k = { }, 0
+ for key, _ in next, t do
+ k = k + 1
+ keys[k] = key
+ end
+ return keys
+ else
+ return { }
end
- return keys
end
local function compare(a,b)
@@ -256,41 +285,49 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
- for key,_ in next, tab do
- s = s + 1
- srt[s] = key
- if category == 3 then
- -- no further check
- else
- local tkey = type(key)
- if tkey == "string" then
- category = (category == 2 and 3) or 1
- elseif tkey == "number" then
- category = (category == 1 and 3) or 2
+ if tab then
+ local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ for key,_ in next, tab do
+ s = s + 1
+ srt[s] = key
+ if category == 3 then
+ -- no further check
else
- category = 3
+ local tkey = type(key)
+ if tkey == "string" then
+ category = (category == 2 and 3) or 1
+ elseif tkey == "number" then
+ category = (category == 1 and 3) or 2
+ else
+ category = 3
+ end
end
end
- end
- if category == 0 or category == 3 then
- sort(srt,compare)
+ if category == 0 or category == 3 then
+ sort(srt,compare)
+ else
+ sort(srt)
+ end
+ return srt
else
- sort(srt)
+ return { }
end
- return srt
end
local function sortedhashkeys(tab) -- fast one
- local srt, s = { }, 0
- for key,_ in next, tab do
- if key then
- s= s + 1
- srt[s] = key
+ if tab then
+ local srt, s = { }, 0
+ for key,_ in next, tab do
+ if key then
+ s= s + 1
+ srt[s] = key
+ end
end
+ sort(srt)
+ return srt
+ else
+ return { }
end
- sort(srt)
- return srt
end
table.sortedkeys = sortedkeys
@@ -315,7 +352,7 @@ end
table.sortedhash = sortedhash
table.sortedpairs = sortedhash
-function table.append(t, list)
+function table.append(t,list)
local n = #t
for i=1,#list do
n = n + 1
@@ -550,12 +587,26 @@ local function do_serialize(root,name,depth,level,indexed)
end
-- we could check for k (index) being number (cardinal)
if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- if compact then
+ -- -- NOT: for k=1,#root do (we need to quit at nil)
+ -- for k,v in ipairs(root) do -- can we use next?
+ -- if not first then first = k end
+ -- last = last + 1
+ -- end
+ -- end
+ local first, last = nil, 0
if compact then
- -- NOT: for k=1,#root do (we need to quit at nil)
- for k,v in ipairs(root) do -- can we use next?
- if not first then first = k end
- last = last + 1
+ last = #root
+ for k=1,last do
+-- if not root[k] then
+ if root[k] == nil then
+ last = k - 1
+ break
+ end
+ end
+ if last > 0 then
+ first = 1
end
end
local sk = sortedkeys(root)
@@ -1027,23 +1078,27 @@ function table.reversed(t)
end
end
-function table.sequenced(t,sep,simple) -- hash only
- local s, n = { }, 0
- for k, v in sortedhash(t) do
- if simple then
- if v == true then
- n = n + 1
- s[n] = k
- elseif v and v~= "" then
+function table.sequenced(t,sep) -- hash only
+ if t then
+ local s, n = { }, 0
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ n = n + 1
+ s[n] = k
+ elseif v and v~= "" then
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
+ end
+ else
n = n + 1
s[n] = k .. "=" .. tostring(v)
end
- else
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
end
+ return concat(s, sep or " | ")
+ else
+ return ""
end
- return concat(s, sep or " | ")
end
function table.print(t,...)
@@ -1124,6 +1179,8 @@ local lpeg = require("lpeg")
-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+-- some code will move to unicode and string
+
local report = texio and texio.write_nl or print
-- local lpmatch = lpeg.match
@@ -1160,8 +1217,8 @@ local report = texio and texio.write_nl or print
-- 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
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-- 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.
@@ -1169,9 +1226,8 @@ local byte, char, gmatch = string.byte, string.char, string.gmatch
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 P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
local utfcharacters = string.utfcharacters
local utfgmatch = unicode and unicode.utf8.gmatch
@@ -1222,6 +1278,10 @@ patterns.utf8char = utf8char
patterns.validutf8 = validutf8char
patterns.validutf8char = validutf8char
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+
patterns.digit = digit
patterns.sign = sign
patterns.cardinal = sign^0 * digit^1
@@ -1241,16 +1301,16 @@ 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.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
patterns.newline = newline
patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.nonspacer = 1 - spacer
+patterns.nonwhitespace = 1 - whitespace
patterns.equal = P("=")
patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.commaspacer = P(",") * spacer^0
patterns.period = P(".")
patterns.colon = P(":")
patterns.semicolon = P(";")
@@ -1265,6 +1325,10 @@ patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
@@ -1275,8 +1339,17 @@ patterns.beginline = #(1-newline)
-- 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?
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
end
function lpeg.splitter(pattern, action)
@@ -1325,7 +1398,7 @@ function string.splitup(str,separator)
if not separator then
separator = ","
end
- return match(splitters_m[separator] or splitat(separator),str)
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
end
@@ -1337,16 +1410,20 @@ function lpeg.split(separator,str)
c = tsplitat(separator)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
end
- return match(c,str)
end
local spacing = patterns.spacer^0 * newline -- sort of strip
@@ -1362,7 +1439,7 @@ local linesplitter = tsplitat(newline)
patterns.linesplitter = linesplitter
function string.splitlines(str)
- return match(linesplitter,str)
+ return lpegmatch(linesplitter,str)
end
local utflinesplitter = utfbom^-1 * tsplitat(newline)
@@ -1370,7 +1447,58 @@ local utflinesplitter = utfbom^-1 * tsplitat(newline)
patterns.utflinesplitter = utflinesplitter
function string.utfsplitlines(str)
- return match(utflinesplitter,str or "")
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
+local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
+
+function string.utfsplit(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+-- inspect(string.utfsplit("a b c d"))
+-- inspect(string.utfsplit("a b c d",true))
+
+-- -- alternative 1: 0.77
+--
+-- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
+--
+-- function string.utflength(str)
+-- return #lpegmatch(utfcharcounter,str or "")
+-- end
+--
+-- -- alternative 2: 1.70
+--
+-- local n = 0
+--
+-- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
+--
+-- function string.utflength(str)
+-- n = 0
+-- lpegmatch(utfcharcounter,str or "")
+-- return n
+-- end
+--
+-- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+local n = 0
+
+local utfcharcounter = utfbom^-1 * Cs ( (
+ Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+)^0 )
+
+function string.utflength(str)
+ n = 0
+ lpegmatch(utfcharcounter,str or "")
+ return n
end
@@ -1384,7 +1512,7 @@ function lpeg.checkedsplit(separator,str)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.checkedsplit(str,separator)
@@ -1395,7 +1523,7 @@ function string.checkedsplit(str,separator)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
@@ -1440,11 +1568,11 @@ function lpeg.keeper(str)
end
function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
+ return (P(str) + P(true)) * Cs(anything^0)
end
function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
+ return Cs((1 - P(str) * endofstring)^0)
end
-- Just for fun I looked at the used bytecode and
@@ -1453,8 +1581,22 @@ end
function lpeg.replacer(one,two)
if type(one) == "table" then
local no = #one
- if no > 0 then
- local p
+ local p
+ if no == 0 then
+ for k, v in next, one do
+ local pp = P(k) / v
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ return Cs(((1-one)^1 + one/two)^0)
+ else
for i=1,no do
local o = one[i]
local pp = P(o[1]) / o[2]
@@ -1467,11 +1609,16 @@ function lpeg.replacer(one,two)
return Cs((p + 1)^0)
end
else
+ one = P(one)
two = two or ""
- return Cs((P(one)/two + 1)^0)
+ return Cs(((1-one)^1 + one/two)^0)
end
end
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -1506,7 +1653,7 @@ local nany = utf8char/""
function lpeg.counter(pattern)
pattern = Cs((P(pattern)/" " + nany)^0)
return function(str)
- return #match(pattern,str)
+ return #lpegmatch(pattern,str)
end
end
@@ -1520,7 +1667,7 @@ if utfgmatch then
end
return n
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -1535,9 +1682,9 @@ else
p = Cs((P(what)/" " + nany)^0)
cache[p] = p
end
- return #match(p,str)
+ return #lpegmatch(p,str)
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -1564,7 +1711,7 @@ 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)
+ return lpegmatch(simple and s or p,str)
end
-- utf extensies
@@ -1611,7 +1758,7 @@ else
p = P(uc)
end
end
- match((utf8char/f)^0,str)
+ lpegmatch((utf8char/f)^0,str)
return p
end
@@ -1627,7 +1774,7 @@ function lpeg.UR(str,more)
first = str
last = more or first
else
- first, last = match(range,str)
+ first, last = lpegmatch(range,str)
if not last then
return P(str)
end
@@ -1654,11 +1801,15 @@ end
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
if type(list) ~= "table" then
list = { list, ... }
end
- -- sort(list) -- longest match first
+ -- table.sort(list) -- longest match first
local p = P(list[1])
for l=2,#list do
p = p + P(list[l])
@@ -1666,10 +1817,6 @@ function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
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.
@@ -1827,6 +1974,24 @@ end
-- utfchar(0x205F), -- math thinspace
-- } )
+-- handy from within tex:
+
+local lpegmatch = lpeg.match
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- strips leading and trailing spaces and collapsed all other spaces
+
+local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
+
+function string.collapsespaces(str)
+ return lpegmatch(pattern,str)
+end
+
end -- of closure
@@ -1851,14 +2016,14 @@ else
io.fileseparator, io.pathseparator = "/" , ":"
end
-function io.loaddata(filename,textmode)
+function io.loaddata(filename,textmode) -- return nil if empty
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
local data = f:read('*all')
f:close()
- return data
- else
- return nil
+ if #data > 0 then
+ return data
+ end
end
end
@@ -1880,6 +2045,45 @@ function io.savedata(filename,data,joiner)
end
end
+function io.loadlines(filename,n) -- return nil if empty
+ local f = io.open(filename,'r')
+ if f then
+ if n then
+ local lines = { }
+ for i=1,n do
+ local line = f:read("*lines")
+ if line then
+ lines[#lines+1] = line
+ else
+ break
+ end
+ end
+ f:close()
+ lines = concat(lines,"\n")
+ if #lines > 0 then
+ return lines
+ end
+ else
+ local line = f:read("*line") or ""
+ assert(f:close())
+ if #line > 0 then
+ return line
+ end
+ end
+ end
+end
+
+function io.loadchunk(filename,n)
+ local f = io.open(filename,'rb')
+ if f then
+ local data = f:read(n or 1024)
+ f:close()
+ if #data > 0 then
+ return data
+ end
+ end
+end
+
function io.exists(filename)
local f = io.open(filename)
if f == nil then
@@ -2107,7 +2311,7 @@ if not modules then modules = { } end modules ['l-number'] = {
-- this module will be replaced when we have the bit library
-local tostring = tostring
+local tostring, tonumber = tostring, tonumber
local format, floor, match, rep = string.format, math.floor, string.match, string.rep
local concat, insert = table.concat, table.insert
local lpegmatch = lpeg.match
@@ -2170,11 +2374,11 @@ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
end
function number.setbit(x, p)
- return hasbit(x, p) and x or x + p
+ return (x % (p + p) >= p) and x or x + p
end
function number.clearbit(x, p)
- return hasbit(x, p) and x - p or x
+ return (x % (p + p) >= p) and x - p or x
end
@@ -2208,6 +2412,10 @@ function number.tobitstring(n,m)
end
+function number.valid(str,default)
+ return tonumber(str) or default or nil
+end
+
end -- of closure
@@ -2319,17 +2527,28 @@ if not modules then modules = { } end modules ['l-os'] = {
-- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
-- os.platform : extended os.name with architecture
+-- os.sleep() => socket.sleep()
+-- math.randomseed(tonumber(string.sub(string.reverse(tostring(math.floor(socket.gettime()*10000))),1,6)))
+
-- maybe build io.flush in os.execute
local os = os
+local date, time = os.date, os.time
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
+local random, ceil, randomseed = math.random, math.ceil, math.randomseed
+local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring
-- The following code permits traversing the environment table, at least
-- in luatex. Internally all environment names are uppercase.
+-- The randomseed in Lua is not that random, although this depends on the operating system as well
+-- as the binary (Luatex is normally okay). But to be sure we set the seed anyway.
+
+math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+
+randomseed(math.initialseed)
+
if not os.__getenv__ then
os.__getenv__ = os.getenv
@@ -2433,12 +2652,14 @@ else
os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
+local launchers = {
+ windows = "start %s",
+ macosx = "open %s",
+ unix = "$BROWSER %s &> /dev/null &",
+}
+
function os.launch(str)
- if os.type == "windows" then
- os.execute("start " .. str) -- os.spawn ?
- else
- os.execute(str .. " &") -- os.spawn ?
- end
+ os.execute(format(launchers[os.name] or launchers.unix,str))
end
if not os.times then
@@ -2649,7 +2870,7 @@ end
local d
function os.timezone(delta)
- d = d or tonumber(tonumber(os.date("%H")-os.date("!%H")))
+ d = d or tonumber(tonumber(date("%H")-date("!%H")))
if delta then
if d > 0 then
return format("+%02i:00",d)
@@ -2661,6 +2882,44 @@ function os.timezone(delta)
end
end
+local timeformat = format("%%s%s",os.timezone(true))
+local dateformat = "!%Y-%m-%d %H:%M:%S"
+
+function os.fulltime(t,default)
+ t = tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = nil
+ end
+ return format(timeformat,date(dateformat,t))
+end
+
+local dateformat = "%Y-%m-%d %H:%M:%S"
+
+function os.localtime(t,default)
+ t = tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = nil
+ end
+ return date(dateformat,t)
+end
+
+function os.converttime(t,default)
+ local t = tonumber(t)
+ if t and t > 0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
+end
+
local memory = { }
local function which(filename)
@@ -2735,7 +2994,7 @@ local function nameonly(name)
return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$",""))
end
-local function extname(name,default)
+local function suffixonly(name,default)
return match(name,"^.+%.([^/\\]-)$") or default or ""
end
@@ -2744,11 +3003,16 @@ local function splitname(name)
return n or name, s or ""
end
-file.basename = basename
-file.dirname = dirname
-file.nameonly = nameonly
-file.extname = extname
-file.suffix = extname
+file.basename = basename
+
+file.pathpart = dirname
+file.dirname = dirname
+
+file.nameonly = nameonly
+
+file.suffixonly = suffixonly
+file.extname = suffixonly -- obsolete
+file.suffix = suffixonly
function file.removesuffix(filename)
return (gsub(filename,"%.[%a%d]+$",""))
@@ -2864,6 +3128,11 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
+function file.size(name)
+ local a = attributes(name)
+ return a and a.size or 0
+end
+
-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -3001,6 +3270,7 @@ local drive = C(R("az","AZ")) * P(":")
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 rest = C(P(1)^0)
drive = drive + Cc("")
path = path + Cc("")
@@ -3009,7 +3279,8 @@ 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)
+local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures
+local pattern_d = path * rest
function file.splitname(str,splitdrive)
if splitdrive then
@@ -3019,6 +3290,10 @@ function file.splitname(str,splitdrive)
end
end
+function file.splitbase(str)
+ return lpegmatch(pattern_d,str) -- returns path, base+suffix
+end
+
function file.nametotable(str,splitdrive) -- returns table
local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
if splitdrive then
@@ -3040,6 +3315,8 @@ function file.nametotable(str,splitdrive) -- returns table
end
end
+-- print(file.splitbase("a/b/c.txt"))
+
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
--
-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
@@ -3081,15 +3358,30 @@ if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
-function file.needs_updating(oldname,newname,threshold) -- size modification access change
- local oldtime = lfs.attributes(oldname, modification)
- local newtime = lfs.attributes(newname, modification)
- if newtime >= oldtime then
- return false
- elseif oldtime - newtime < (threshold or 1) then
- return false
+function file.needsupdating(oldname,newname,threshold) -- size modification access change
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime = lfs.attributes(newname,"modification")
+ if not newtime then
+ return true -- no new file, so no updating needed
+ elseif newtime >= oldtime then
+ return false -- new file definitely needs updating
+ elseif oldtime - newtime < (threshold or 1) then
+ return false -- new file is probably still okay
+ else
+ return true -- new file has to be updated
+ end
else
- return true
+ return false -- no old file, so no updating needed
+ end
+end
+
+file.needs_updating = file.needsupdating
+
+function file.syncmtimes(oldname,newname)
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
end
end
@@ -3111,7 +3403,7 @@ function file.loadchecksum(name)
return nil
end
-function file.savechecksum(name, checksum)
+function file.savechecksum(name,checksum)
if not checksum then checksum = file.checksum(name) end
if checksum then
io.savedata(name .. ".md5",checksum)
@@ -3136,7 +3428,7 @@ if not modules then modules = { } end modules ['l-url'] = {
local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find
local concat = table.concat
local tonumber, type = tonumber, type
-local P, C, R, S, Cs, Cc, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct
+local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V
local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer
-- from wikipedia:
@@ -3169,15 +3461,19 @@ local endofstring = P(-1)
local hexdigit = R("09","AF","af")
local plus = P("+")
local nothing = Cc("")
-local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
+local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar
+local escaped = (plus / " ") + escapedchar
-- 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
+--
+-- maybe we should already split the query (better for unescaping as = & can be part of a value
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)
+----- querystr = Cs((escaped+(1- hash))^0)
+local querystr = Cs(( (1- hash))^0)
local fragmentstr = Cs((escaped+(1- endofstring))^0)
local scheme = schemestr * colon + nothing
@@ -3192,11 +3488,20 @@ local parser = Ct(validurl)
lpegpatterns.url = validurl
lpegpatterns.urlsplitter = parser
-local escapes = { } ; for i=0,255 do escapes[i] = format("%%%02X",i) end
+local escapes = { }
+
+setmetatable(escapes, { __index = function(t,k)
+ local v = format("%%%02X",byte(k))
+ t[k] = v
+ return v
+end })
-local escaper = Cs((R("09","AZ","az") + S("-./_") + P(1) / escapes)^0)
+local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most
+local unescaper = Cs((escapedchar + 1)^0)
-lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaped = escapedchar
+lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaper = unescaper
-- todo: reconsider Ct as we can as well have five return values (saves a table)
-- so we can have two parsers, one with and one without
@@ -3208,8 +3513,12 @@ end
local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
local function hasscheme(str)
- local scheme = lpegmatch(isscheme,str) -- at least one character
- return scheme ~= "" and scheme or false
+ if str then
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
+ else
+ return false
+ end
end
@@ -3228,10 +3537,32 @@ local rootbased = P("/")
local barswapper = replacer("|",":")
local backslashswapper = replacer("\\","/")
+-- queries:
+
+local equal = P("=")
+local amp = P("&")
+local key = Cs(((escapedchar+1)-equal )^0)
+local value = Cs(((escapedchar+1)-amp -endofstring)^0)
+
+local splitquery = Cf ( Ct("") * P { "sequence",
+ sequence = V("pair") * (amp * V("pair"))^0,
+ pair = Cg(key * equal * value),
+}, rawset)
+
+-- hasher
+
local function hashed(str) -- not yet ok (/test?test)
+ if str == "" then
+ return {
+ scheme = "invalid",
+ original = str,
+ }
+ end
local s = split(str)
- local somescheme = s[1] ~= ""
- local somequery = s[4] ~= ""
+ local rawscheme = s[1]
+ local rawquery = s[4]
+ local somescheme = rawscheme ~= ""
+ local somequery = rawquery ~= ""
if not somescheme and not somequery then
s = {
scheme = "file",
@@ -3247,14 +3578,17 @@ local function hashed(str) -- not yet ok (/test?test)
local authority, path, filename = s[2], s[3]
if authority == "" then
filename = path
+ elseif path == "" then
+ filename = ""
else
filename = authority .. "/" .. path
end
s = {
- scheme = s[1],
+ scheme = rawscheme,
authority = authority,
path = path,
- query = s[4],
+ query = lpegmatch(unescaper,rawquery), -- unescaped, but possible conflict with & and =
+ queries = lpegmatch(splitquery,rawquery), -- split first and then unescaped
fragment = s[5],
original = str,
noscheme = false,
@@ -3264,6 +3598,8 @@ local function hashed(str) -- not yet ok (/test?test)
return s
end
+-- inspect(hashed("template://test"))
+
-- Here we assume:
--
-- files: /// = relative
@@ -3306,23 +3642,65 @@ function url.construct(hash) -- dodo: we need to escape !
return lpegmatch(escaper,concat(fullurl))
end
-function url.filename(filename)
+function url.filename(filename) -- why no lpeg here ?
local t = hashed(filename)
return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename
end
+local function escapestring(str)
+ return lpegmatch(escaper,str)
+end
+
+url.escape = escapestring
+
+-- function url.query(str) -- separator could be an option
+-- if type(str) == "string" then
+-- local t = { }
+-- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
+-- t[k] = v
+-- end
+-- return t
+-- else
+-- return str
+-- end
+-- end
+
function url.query(str)
if type(str) == "string" then
- local t = { }
- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
- t[k] = v
- end
- return t
+ return lpegmatch(splitquery,str) or ""
else
return str
end
end
+function url.toquery(data)
+ local td = type(data)
+ if td == "string" then
+ return #str and escape(data) or nil -- beware of double escaping
+ elseif td == "table" then
+ if next(data) then
+ local t = { }
+ for k, v in next, data do
+ t[#t+1] = format("%s=%s",k,escapestring(v))
+ end
+ return concat(t,"&")
+ end
+ else
+ -- nil is a signal that no query
+ end
+end
+
+-- /test/ | /test | test/ | test => test
+
+function url.barepath(path)
+ if not path or path == "" then
+ return ""
+ else
+ return (gsub(path,"^/?(.-)/?$","%1"))
+ end
+end
+
+
@@ -3363,6 +3741,24 @@ local isdir = lfs.isdir
local isfile = lfs.isfile
local currentdir = lfs.currentdir
+-- in case we load outside luatex
+
+if not isdir then
+ function isdir(name)
+ local a = attributes(name)
+ return a and a.mode == "directory"
+ end
+ lfs.isdir = isdir
+end
+
+if not isfile then
+ function isfile(name)
+ local a = attributes(name)
+ return a and a.mode == "file"
+ end
+ lfs.isfile = isfile
+end
+
-- handy
function dir.current()
@@ -3738,28 +4134,49 @@ function boolean.tonumber(b)
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
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
elseif str == "true" then
return true
elseif str == "false" then
return false
+ elseif not tolerant then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
else
- return str
+ return str == "yes" or str == "on" or str == "t"
end
end
string.toboolean = toboolean
+function string.booleanstring(str)
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
+ else
+ return str == "yes" or str == "on" or str == "t"
+ end
+end
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -3784,57 +4201,229 @@ if not modules then modules = { } end modules ['l-unicode'] = {
license = "see context related readme files"
}
+-- this module will be reorganized
+
+-- todo: utf.sub replacement (used in syst-aux)
+
+local concat = table.concat
+local type = type
+local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local utftype = patterns.utftype
+local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
+local utfsplitlines = string.utfsplitlines
+
if not unicode then
- unicode = { utf8 = { } }
+ unicode = { }
+
+end
+
+local unicode = unicode
+
+utf = utf or unicode.utf8
+
+if not utf then
+
+ utf8 = { }
+ unicode.utf8 = utf8
+ utf = utf8
+
+end
+
+if not utf.char then
local floor, char = math.floor, string.char
- function unicode.utf8.utfchar(n)
+ function utf.char(n)
if n < 0x80 then
+ -- 0aaaaaaa : 0x80
return char(n)
elseif n < 0x800 then
+ -- 110bbbaa : 0xC0 : n >> 6
+ -- 10aaaaaa : 0x80 : n & 0x3F
return char(
0xC0 + floor(n/0x40),
0x80 + (n % 0x40)
)
elseif n < 0x10000 then
+ -- 1110bbbb : 0xE0 : n >> 12
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
return char(
0xE0 + floor(n/0x1000),
0x80 + (floor(n/0x40) % 0x40),
0x80 + (n % 0x40)
)
- elseif n < 0x40000 then
+ elseif n < 0x200000 then
+ -- 11110ccc : 0xF0 : n >> 18
+ -- 10ccbbbb : 0x80 : (n >> 12) & 0x3F
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
+ -- dddd : ccccc - 1
return char(
- 0xF0 + floor(n/0x40000),
- 0x80 + floor(n/0x1000),
+ 0xF0 + floor(n/0x40000),
+ 0x80 + (floor(n/0x1000) % 0x40),
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 "?"
+ return ""
end
end
end
-local unicode = unicode
+if not utf.byte then
+
+ local utf8byte = patterns.utf8byte
+
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+
+end
+
+local utfchar, utfbyte = utf.char, utf.byte
+
+-- As we want to get rid of the (unmaintained) utf library we implement our own
+-- variants (in due time an independent module):
+
+function unicode.filetype(data)
+ return data and lpegmatch(utftype,data) or "unknown"
+end
+
+local toentities = 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
-utf = utf or unicode.utf8
-local concat = table.concat
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
-local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-local type = type
-local utfsplitlines = string.utfsplitlines
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+-- actually one of them is already utf ... sort of useless this one
+
+-- function utf.char(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
+--
+-- merge into:
+
+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
+
+local validatedutf = Cs (
+ (
+ patterns.utf8one
+ + patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ + P(1) / "�"
+ )^0
+)
+
+patterns.validatedutf = validatedutf
+
+function string.validutf(str)
+ return lpegmatch(validatedutf,str)
+end
+
+
+utf.length = string.utflength
+utf.split = string.utfsplit
+utf.splitines = string.utfsplitlines
+utf.valid = string.validutf
+
+if not utf.len then
+ utf.len = utf.length
+end
+
+-- a replacement for simple gsubs:
+
+local utf8char = patterns.utf8char
+
+function utf.remapper(mapping)
+ local pattern = Cs((utf8char/mapping)^0)
+ return function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end, pattern
+end
+
+-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
+-- print(remap("abcd 1234 abcd"))
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
@@ -4027,11 +4616,22 @@ local function big(c)
end
end
+-- function unicode.utf8_to_utf16(str,littleendian)
+-- if littleendian then
+-- return char(255,254) .. utfgsub(str,".",little)
+-- else
+-- return char(254,255) .. utfgsub(str,".",big)
+-- end
+-- end
+
+local _, l_remap = utf.remapper(little)
+local _, b_remap = utf.remapper(big)
+
function unicode.utf8_to_utf16(str,littleendian)
if littleendian then
- return char(255,254) .. utfgsub(str,".",little)
+ return char(255,254) .. lpegmatch(l_remap,str)
else
- return char(254,255) .. utfgsub(str,".",big)
+ return char(254,255) .. lpegmatch(b_remap,str)
end
end
@@ -4052,84 +4652,12 @@ function unicode.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
+--
-local lpegmatch = lpeg.match
-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)
-
--- actually one of them is already utf ... sort of useless this one
-
-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
-
-local validatedutf = Cs (
- (
- patterns.utf8one
- + patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- + P(1) / "�"
- )^0
-)
-
-patterns.validatedutf = validatedutf
+local pattern = Ct(C(patterns.utf8char)^0)
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
+function utf.totable(str)
+ return lpegmatch(pattern,str)
end
@@ -4189,10 +4717,11 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch, rep = string.format, string.gmatch, string.rep
+local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub
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
+local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring
+local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -4346,6 +4875,121 @@ function tables.encapsulate(core,capsule,protect)
end
end
+local function serialize(t,r,outer) -- no mixes
+ r[#r+1] = "{"
+ local n = #t
+ if n > 0 then
+ for i=1,n do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("%q,",v)
+ elseif tv == "number" then
+ r[#r+1] = format("%s,",v)
+ elseif tv == "table" then
+ serialize(v,r)
+ elseif tv == "boolean" then
+ r[#r+1] = format("%s,",tostring(v))
+ end
+ end
+ else
+ for k, v in next, t do
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("[%q]=%q,",k,v)
+ elseif tv == "number" then
+ r[#r+1] = format("[%q]=%s,",k,v)
+ elseif tv == "table" then
+ r[#r+1] = format("[%q]=",k)
+ serialize(v,r)
+ elseif tv == "boolean" then
+ r[#r+1] = format("[%q]=%s,",k,tostring(v))
+ end
+ end
+ end
+ if outer then
+ r[#r+1] = "}"
+ else
+ r[#r+1] = "},"
+ end
+ return r
+end
+
+function table.fastserialize(t,prefix)
+ return concat(serialize(t,{ prefix or "return" },true))
+end
+
+function table.deserialize(str)
+ if not str or str == "" then
+ return
+ end
+ local code = loadstring(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
+end
+
+-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
+
+function table.load(filename)
+ if filename then
+ local t = io.loaddata(filename)
+ if t and t ~= "" then
+ t = loadstring(t)
+ if type(t) == "function" then
+ t = t()
+ if type(t) == "table" then
+ return t
+ end
+ end
+ end
+ end
+end
+
+local function slowdrop(t)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = format("%s=%q",k,v)
+ end
+ r[i] = format(" {%s},\n",concat(l))
+ end
+ return format("return {\n%s}",concat(r))
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ for i=1,#t do
+ local ti = t[i]
+ r[#r+1] = " {"
+ for k, v in next, ti do
+ r[#r+1] = format("%s=%q",k,v)
+ end
+ r[#r+1] = "},\n"
+ end
+ r[#r+1] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow)
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
+
end -- of closure
@@ -4520,11 +5164,10 @@ local concat = table.concat
local type, next = type, next
utilities = utilities or {}
-utilities.merger = utilities.merger or { } -- maybe mergers
+local merger = utilities.merger or { }
+utilities.merger = merger
utilities.report = logs and logs.reporter("system") or print
-local merger = utilities.merger
-
merger.strip_comment = true
local m_begin_merge = "begin library merge"
@@ -4570,9 +5213,11 @@ end
local function self_save(name, data)
if data ~= "" then
if merger.strip_comment then
- -- saves some 20K
local n = #data
+ -- saves some 20K .. scite comments
data = gsub(data,"%-%-~[^\n\r]*[\r\n]","")
+ -- saves some 20K .. ldx comments
+ data = gsub(data,"%-%-%[%[ldx%-%-.-%-%-ldx%]%]%-%-","")
utilities.report("merge: %s bytes of comment stripped, %s bytes of code left",n-#data,#data)
end
io.savedata(name,data)
@@ -4653,36 +5298,208 @@ if not modules then modules = { } end modules ['util-lua'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment = "the strip code is written by Peter Cawley",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-utilities = utilities or {}
-utilities.lua = utilities.lua or { }
-utilities.report = logs and logs.reporter("system") or print
+local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
+local loadstring, loadfile, type = loadstring, loadfile, type
-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)
+utilities = utilities or {}
+utilities.lua = utilities.lua or { }
+local luautilities = utilities.lua
+
+utilities.report = logs and logs.reporter("system") or print -- can be overloaded later
+
+local tracestripping = false
+local forcestupidcompile = true -- use internal bytecode compiler
+luautilities.stripcode = true -- support stripping when asked for
+luautilities.alwaysstripcode = false -- saves 1 meg on 7 meg compressed format file (2012.08.12)
+luautilities.nofstrippedchunks = 0
+luautilities.nofstrippedbytes = 0
+
+-- The next function was posted by Peter Cawley on the lua list and strips line
+-- number information etc. from the bytecode data blob. We only apply this trick
+-- when we store data tables. Stripping makes the compressed format file about
+-- 1MB smaller (and uncompressed we save at least 6MB).
+--
+-- You can consider this feature an experiment, so it might disappear. There is
+-- no noticeable gain in runtime although the memory footprint should be somewhat
+-- smaller (and the file system has a bit less to deal with).
+--
+-- Begin of borrowed code ... works for Lua 5.1 which LuaTeX currently uses ...
+
+local function strip_code_pc(dump,name)
+ local before = #dump
+ local version, format, endian, int, size, ins, num = byte(dump,5,11)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
end
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
+ end
+ end
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ end
+ end
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. sub(dump,dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(sub(dump,offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
+ end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. rep("\0", int * 3)
+ return stripped, offset
+ end
+ dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
+ local after = #dump
+ local delta = before-after
+ if tracestripping then
+ utilities.report("stripped bytecode: %s, before %s, after %s, delta %s",name or "unknown",before,after,delta)
+ end
+ luautilities.nofstrippedchunks = luautilities.nofstrippedchunks + 1
+ luautilities.nofstrippedbytes = luautilities.nofstrippedbytes + delta
+ return dump, delta
+end
+
+-- ... end of borrowed code.
+
+local function strippedbytecode(code,forcestrip,name)
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ return strip_code_pc(code,name)
+ else
+ return code, 0
end
end
-function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
+luautilities.stripbytecode = strip_code_pc
+luautilities.strippedbytecode = strippedbytecode
+
+local function fatalerror(name)
+ utilities.report(format("fatal error in %q",name or "unknown"))
+end
+
+-- quite subtle ... doing this wrong incidentally can give more bytes
+
+
+function luautilities.loadedluacode(fullname,forcestrip,name)
+ -- quite subtle ... doing this wrong incidentally can give more bytes
+ name = name or fullname
+ local code = loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip) == "function" then
+ forcestrip = forcestrip(fullname)
+ end
+ if forcestrip then
+ local code, n = strip_code_pc(dump(code,name))
+ return loadstring(code), n
+ elseif luautilities.alwaysstripcode then
+ return loadstring(strip_code_pc(dump(code),name))
+ else
+ return code, 0
+ end
+ elseif luautilities.alwaysstripcode then
+ return loadstring(strip_code_pc(dump(code),name))
+ else
+ return code, 0
+ end
+end
+
+function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
+ local n = 0
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ code = loadstring(code)
+ if not code then
+ fatalerror(name)
+ end
+ code, n = strip_code_pc(dump(code),name)
+ end
+ return loadstring(code), n
+end
+
+local function stupidcompile(luafile,lucfile,strip)
+ local code = io.loaddata(luafile)
+ local n = 0
+ if code and code ~= "" then
+ code = loadstring(code)
+ if not code then
+ fatalerror()
+ end
+ code = dump(code)
+ if strip then
+ code, n = strippedbytecode(code,true,luafile) -- last one is reported
+ end
+ if code and code ~= "" then
+ io.savedata(lucfile,code)
+ end
+ end
+ return n
+end
+
+local luac_normal = "texluac -o %q %q"
+local luac_strip = "texluac -s -o %q %q"
+
+function luautilities.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)
+ local done = false
if strip ~= false then
- command = "-s " .. command
+ strip = true
+ end
+ if forcestupidcompile then
+ fallback = true
+ elseif strip then
+ done = os.spawn(format(luac_strip, lucfile,luafile)) == 0
+ else
+ done = os.spawn(format(luac_normal,lucfile,luafile)) == 0
end
- 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
+ local n = stupidcompile(luafile,lucfile,strip)
+ if n > 0 then
+ utilities.report("lua: %s dumped into %s (%i bytes stripped)",luafile,lucfile,n)
+ else
+ utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile)
+ end
+ cleanup = false -- better see how bad it is
end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
@@ -4697,7 +5514,6 @@ end
-
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -4710,8 +5526,10 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-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 lpeg, table, string = lpeg, table, string
+
+local P, R, V, S, C, Ct, Cs, Carg, Cc = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
@@ -4723,29 +5541,39 @@ parsers.patterns = parsers.patterns or { }
local setmetatableindex = table.setmetatableindex
local sortedhash = table.sortedhash
+-- we share some patterns
+
+local space = P(' ')
+local equal = P("=")
+local comma = P(",")
+local lbrace = P("{")
+local rbrace = P("}")
+local period = S(".")
+local punctuation = S(".,:;")
+local spacer = patterns.spacer
+local whitespace = patterns.whitespace
+local newline = patterns.newline
+local anything = patterns.anything
+local endofstring = patterns.endofstring
+
-- we could use a Cf Cg construct
local escape, left, right = P("\\"), P('{'), P('}')
-lpeg.patterns.balanced = P {
+patterns.balanced = P {
[1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0,
[2] = left * V(1) * right
}
-local space = P(' ')
-local equal = P("=")
-local comma = P(",")
-local lbrace = P("{")
-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
+local content = (1-endofstring)^0
-lpeg.patterns.nested = nested -- no capture
-lpeg.patterns.argument = argument -- argument after e.g. =
-lpeg.patterns.content = content -- rest after e.g =
+patterns.nested = nested -- no capture
+patterns.argument = argument -- argument after e.g. =
+patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4764,10 +5592,6 @@ local function set(key,value)
hash[key] = value
end
-local function set(key,value)
- hash[key] = value
-end
-
local pattern_a_s = (pattern_a/set)^1
local pattern_b_s = (pattern_b/set)^1
local pattern_c_s = (pattern_c/set)^1
@@ -4818,7 +5642,7 @@ end
local separator = comma * space^0
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-local pattern = Ct(value*(separator*value)^0)
+local pattern = spaces * Ct(value*(separator*value)^0)
-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
@@ -4942,6 +5766,37 @@ function parsers.listitem(str)
return gmatch(str,"[^, ]+")
end
+--
+local digit = R("09")
+
+local pattern = Cs { "start",
+ start = V("one") + V("two") + V("three"),
+ rest = (Cc(",") * V("thousand"))^0 * (P(".") + endofstring) * anything^0,
+ thousand = digit * digit * digit,
+ one = digit * V("rest"),
+ two = digit * digit * V("rest"),
+ three = V("thousand") * V("rest"),
+}
+
+patterns.splitthousands = pattern -- maybe better in the parsers namespace ?
+
+function parsers.splitthousands(str)
+ return lpegmatch(pattern,str) or str
+end
+
+-- print(parsers.splitthousands("11111111111.11"))
+
+local optionalwhitespace = whitespace^0
+
+patterns.words = Ct((Cs((1-punctuation-whitespace)^1) + anything)^1)
+patterns.sentences = Ct((optionalwhitespace * Cs((1-period)^0 * period))^1)
+patterns.paragraphs = Ct((optionalwhitespace * Cs((whitespace^1*endofstring/"" + 1 - (spacer^0*newline*newline))^1))^1)
+
+-- local str = " Word1 word2. \n Word3 word4. \n\n Word5 word6.\n "
+-- inspect(lpegmatch(patterns.paragraphs,str))
+-- inspect(lpegmatch(patterns.sentences,str))
+-- inspect(lpegmatch(patterns.words,str))
+
end -- of closure
@@ -5043,7 +5898,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util.deb'] = {
+if not modules then modules = { } end modules ['util-deb'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -5155,6 +6010,7 @@ function inspect(i) -- global function
else
print(tostring(i))
end
+ return i -- so that we can inline the inspect
end
-- from the lua book:
@@ -5194,7 +6050,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
-local write_nl = texio.write_nl
+local write_nl = texio and texio.write_nl or print
statistics = statistics or { }
local statistics = statistics
@@ -5277,7 +6133,7 @@ statistics.elapsedtime = elapsedtime
statistics.elapsedindeed = elapsedindeed
statistics.elapsedseconds = elapsedseconds
--- general function
+-- general function .. we might split this module
function statistics.register(tag,fnc)
if statistics.enable and type(fnc) == "function" then
@@ -5387,6 +6243,8 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
license = "see context related readme files"
}
+-- maybe this should be util-set.lua
+
local type, next, tostring = type, next, tostring
local concat = table.concat
local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
@@ -5586,7 +6444,7 @@ function setters.show(t)
local value, default, modules = functions.value, functions.default, #functions
value = value == nil and "unset" or tostring(value)
default = default == nil and "unset" or tostring(default)
- t.report("%-30s modules: %2i default: %6s value: %6s",name,modules,default,value)
+ t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value)
end
end
t.report()
@@ -5678,17 +6536,31 @@ end)
-- experiment
-local flags = environment and environment.engineflags
+if environment then
-if flags then
- if trackers and flags.trackers then
- setters.initialize("flags","trackers", settings_to_hash(flags.trackers))
- -- t_enable(flags.trackers)
- end
- if directives and flags.directives then
- setters.initialize("flags","directives", settings_to_hash(flags.directives))
- -- d_enable(flags.directives)
+ -- The engineflags are known earlier than environment.arguments but maybe we
+ -- need to handle them both as the later are parsed differently. The c: prefix
+ -- is used by mtx-context to isolate the flags from those that concern luatex.
+
+ local engineflags = environment.engineflags
+
+ if engineflags then
+ if trackers then
+ local list = engineflags["c:trackers"] or engineflags["trackers"]
+ if type(list) == "string" then
+ setters.initialize("flags","trackers",settings_to_hash(list))
+ -- t_enable(list)
+ end
+ end
+ if directives then
+ local list = engineflags["c:directives"] or engineflags["directives"]
+ if type(list) == "string" then
+ setters.initialize("flags","directives", settings_to_hash(list))
+ -- d_enable(list)
+ end
+ end
end
+
end
-- here
@@ -5741,10 +6613,7 @@ local next, type = next, type
local setmetatableindex = table.setmetatableindex
---[[ldx--
-<p>This is a prelude to a more extensive logging module. We no longer
-provide <l n='xml'/> based logging a sparsing is relatively easy anyway.</p>
---ldx]]--
+
logs = logs or { }
local logs = logs
@@ -6560,7 +7429,8 @@ local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
local unquoted, quoted = string.unquoted, string.quoted
-local concat = table.concat
+local concat, insert, remove = table.concat, table.insert, table.remove
+local loadedluacode = utilities.lua.loadedluacode
-- precautions
@@ -6578,8 +7448,28 @@ if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaon
for k=3,#arg do
arg[k-2] = arg[k]
end
- arg[#arg] = nil -- last
- arg[#arg] = nil -- pre-last
+ remove(arg) -- last
+ remove(arg) -- pre-last
+end
+
+-- This is an ugly hack but it permits symlinking a script (say 'context') to 'mtxrun' as in:
+--
+-- ln -s /opt/minimals/tex/texmf-linux-64/bin/mtxrun context
+--
+-- The special mapping hack is needed because 'luatools' boils down to 'mtxrun --script base'
+-- but it's unlikely that there will be more of this
+
+do
+
+ local originalzero = file.basename(arg[0])
+ local specialmapping = { luatools == "base" }
+
+ if originalzero ~= "mtxrun" and originalzero ~= "mtxrun.lua" then
+ arg[0] = specialmapping[originalzero] or originalzero
+ insert(arg,0,"--script")
+ insert(arg,0,"mtxrun")
+ end
+
end
-- environment
@@ -6619,6 +7509,8 @@ local mt = {
setmetatable(environment,mt)
+-- context specific arguments (in order not to confuse the engine)
+
function environment.initializearguments(arg)
local arguments, files = { }, { }
environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
@@ -6627,10 +7519,12 @@ function environment.initializearguments(arg)
if index > 0 then
local flag, value = match(argument,"^%-+(.-)=(.-)$")
if flag then
+ flag = gsub(flag,"^c:","")
arguments[flag] = unquoted(value or "")
else
flag = match(argument,"^%-+(.+)")
if flag then
+ flag = gsub(flag,"^c:","")
arguments[flag] = true
else
files[#files+1] = argument
@@ -6650,7 +7544,7 @@ end
-- tricky: too many hits when we support partials unless we add
-- a registration of arguments so from now on we have 'partial'
-function environment.argument(name,partial)
+function environment.getargument(name,partial)
local arguments, sortedflags = environment.arguments, environment.sortedflags
if arguments[name] then
return arguments[name]
@@ -6673,6 +7567,8 @@ function environment.argument(name,partial)
return nil
end
+environment.argument = environment.getargument
+
function environment.splitarguments(separator) -- rather special, cut-off before separator
local done, before, after = false, { }, { }
local originalarguments = environment.originalarguments
@@ -6758,7 +7654,7 @@ function environment.texfile(filename)
return resolvers.findfile(filename,'tex')
end
-function environment.luafile(filename)
+function environment.luafile(filename) -- needs checking
local resolved = resolvers.findfile(filename,'tex') or ""
if resolved ~= "" then
return resolved
@@ -6770,13 +7666,16 @@ function environment.luafile(filename)
return resolvers.findfile(filename,'luatexlibs') or ""
end
-environment.loadedluacode = loadfile -- can be overloaded
+local function checkstrip(filename)
+ local modu = modules[file.nameonly(filename)]
+ return modu and modu.dataonly
+end
function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format
filename = file.replacesuffix(filename, "lua")
local fullname = environment.luafile(filename)
if fullname and fullname ~= "" then
- local data = environment.loadedluacode(fullname)
+ local data = loadedluacode(fullname,checkstrip,filename)
if trace_locating then
report_lua("loading file %s%s", fullname, not data and " failed" or "")
elseif not silent then
@@ -6874,21 +7773,7 @@ local trace_entities = false trackers.register("xml.entities", function(v) trac
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
---[[ldx--
-<p>The parser used here is inspired by the variant discussed in the lua book, but
-handles comment and processing instructions, has a different structure, provides
-parent access; a first version used different trickery but was less optimized to we
-went this route. First we had a find based parser, now we have an <l n='lpeg'/> based one.
-The find based parser can be found in l-xml-edu.lua along with other older code.</p>
-
-<p>Beware, the interface may change. For instance at, ns, tg, dt may get more
-verbose names. Once the code is stable we will also remove some tracing and
-optimize the code.</p>
-<p>I might even decide to reimplement the parser using the latest <l n='lpeg'/> trickery
-as the current variant was written when <l n='lpeg'/> showed up and it's easier now to
-build tables in one go.</p>
---ldx]]--
xml = xml or { }
local xml = xml
@@ -6898,46 +7783,25 @@ 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, utffind, utfgsub = utf.char, utf.find, utf.gsub
+local utfchar = utf.char
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
---[[ldx--
-<p>First a hack to enable namespace resolving. A namespace is characterized by
-a <l n='url'/>. The following function associates a namespace prefix with a
-pattern. We use <l n='lpeg'/>, which in this case is more than twice as fast as a
-find based solution where we loop over an array of patterns. Less code and
-much cleaner.</p>
---ldx]]--
+
xml.xmlns = xml.xmlns or { }
local check = P(false)
local parse = check
---[[ldx--
-<p>The next function associates a namespace prefix with an <l n='url'/>. This
-normally happens independent of parsing.</p>
-<typing>
-xml.registerns("mml","mathml")
-</typing>
---ldx]]--
function xml.registerns(namespace, pattern) -- pattern can be an lpeg
check = check + C(P(lower(pattern))) / namespace
parse = P { P(check) + 1 * V(1) }
end
---[[ldx--
-<p>The next function also registers a namespace, but this time we map a
-given namespace prefix onto a registered one, using the given
-<l n='url'/>. This used for attributes like <t>xmlns:m</t>.</p>
-<typing>
-xml.checkns("m","http://www.w3.org/mathml")
-</typing>
---ldx]]--
function xml.checkns(namespace,url)
local ns = lpegmatch(parse,lower(url))
@@ -6946,66 +7810,15 @@ function xml.checkns(namespace,url)
end
end
---[[ldx--
-<p>Next we provide a way to turn an <l n='url'/> into a registered
-namespace. This used for the <t>xmlns</t> attribute.</p>
-
-<typing>
-resolvedns = xml.resolvens("http://www.w3.org/mathml")
-</typing>
-This returns <t>mml</t>.
---ldx]]--
function xml.resolvens(url)
return lpegmatch(parse,lower(url)) or ""
end
---[[ldx--
-<p>A namespace in an element can be remapped onto the registered
-one efficiently by using the <t>xml.xmlns</t> table.</p>
---ldx]]--
-
---[[ldx--
-<p>This version uses <l n='lpeg'/>. We follow the same approach as before, stack and top and
-such. This version is about twice as fast which is mostly due to the fact that
-we don't have to prepare the stream for cdata, doctype etc etc. This variant is
-is dedicated to Luigi Scarso, who challenged me with 40 megabyte <l n='xml'/> files that
-took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
-the <l n='lpeg'/> implementation we got that down to less 7.3 seconds. Loading the 14
-<l n='context'/> interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.</p>
-
-<p>Next comes the parser. The rather messy doctype definition comes in many
-disguises so it is no surprice that later on have to dedicate quite some
-<l n='lpeg'/> code to it.</p>
-
-<typing>
-<!DOCTYPE Something PUBLIC "... ..." "..." [ ... ] >
-<!DOCTYPE Something PUBLIC "... ..." "..." >
-<!DOCTYPE Something SYSTEM "... ..." [ ... ] >
-<!DOCTYPE Something SYSTEM "... ..." >
-<!DOCTYPE Something [ ... ] >
-<!DOCTYPE Something >
-</typing>
-
-<p>The code may look a bit complex but this is mostly due to the fact that we
-resolve namespaces and attach metatables. There is only one public function:</p>
-
-<typing>
-local x = xml.convert(somestring)
-</typing>
-
-<p>An optional second boolean argument tells this function not to create a root
-element.</p>
-
-<p>Valid entities are:</p>
-
-<typing>
-<!ENTITY xxxx SYSTEM "yyyy" NDATA zzzz>
-<!ENTITY xxxx PUBLIC "yyyy" >
-<!ENTITY xxxx "yyyy" >
-</typing>
---ldx]]--
+
+
+
-- not just one big nested table capture (lpeg overflow)
@@ -7220,15 +8033,7 @@ 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 escaped = utf.remapper(privates_u)
local function unescaped(s)
local p = privates_n[s]
@@ -7243,13 +8048,7 @@ local function unescaped(s)
return p
end
-local function unprivatized(s,resolve)
- if s == "" then
- return ""
- else
- return (utfgsub(s,".",privates_p))
- end
-end
+local unprivatized = utf.remapper(privates_p)
xml.privatetoken = unescaped
xml.unprivatized = unprivatized
@@ -7589,7 +8388,12 @@ local function _xmlconvert_(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler(format("load error: %s",errorstr))
+ local currentresource = settings.currentresource
+ if currentresource and currentresource ~= "" then
+ xml.errorhandler(format("load error in [%s]: %s",currentresource,errorstr))
+ else
+ xml.errorhandler(format("load error: %s",errorstr))
+ end
end
end
else
@@ -7634,7 +8438,7 @@ function xmlconvert(data,settings)
if ok then
return result
else
- return _xmlconvert_("")
+ return _xmlconvert_("",settings)
end
end
@@ -7655,10 +8459,7 @@ function xml.inheritedconvert(data,xmldata) -- xmldata is parent
return xc
end
---[[ldx--
-<p>Packaging data in an xml like table is done with the following
-function. Maybe it will go away (when not used).</p>
---ldx]]--
+
function xml.is_valid(root)
return root and root.dt and root.dt[1] and type(root.dt[1]) == "table" and not root.dt[1].er
@@ -7677,11 +8478,7 @@ end
xml.errorhandler = report_xml
---[[ldx--
-<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
-the whole file first. The function accepts a string representing
-a filename or a file handle.</p>
---ldx]]--
+
function xml.load(filename,settings)
local data = ""
@@ -7695,13 +8492,17 @@ function xml.load(filename,settings)
elseif filename then -- filehandle
data = filename:read("*all")
end
- return xmlconvert(data,settings)
+ if settings then
+ settings.currentresource = filename
+ local result = xmlconvert(data,settings)
+ settings.currentresource = nil
+ return result
+ else
+ return xmlconvert(data,{ currentresource = filename })
+ end
end
---[[ldx--
-<p>When we inject new elements, we need to convert strings to
-valid trees, which is what the next function does.</p>
---ldx]]--
+
local no_root = { no_root = true }
@@ -7714,11 +8515,7 @@ function xml.toxml(data)
end
end
---[[ldx--
-<p>For copying a tree we use a dedicated function instead of the
-generic table copier. Since we know what we're dealing with we
-can speed up things a bit. The second argument is not to be used!</p>
---ldx]]--
+
local function copy(old,tables)
if old then
@@ -7742,13 +8539,7 @@ end
xml.copy = copy
---[[ldx--
-<p>In <l n='context'/> serializing the tree or parts of the tree is a major
-actitivity which is why the following function is pretty optimized resulting
-in a few more lines of code than needed. The variant that uses the formatting
-function for all components is about 15% slower than the concatinating
-alternative.</p>
---ldx]]--
+
-- todo: add <?xml version='1.0' standalone='yes'?> when not present
@@ -7761,15 +8552,12 @@ function xml.checkbom(root) -- can be made faster
return
end
end
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 1, { special = true, ns = "", tg = "@pi@", dt = { "xml version='1.0' standalone='yes'" } } )
insert(dt, 2, "\n" )
end
end
---[[ldx--
-<p>At the cost of some 25% runtime overhead you can first convert the tree to a string
-and then handle the lot.</p>
---ldx]]--
+
-- new experimental reorganized serialize
@@ -7962,21 +8750,7 @@ newhandlers {
}
}
---[[ldx--
-<p>How you deal with saving data depends on your preferences. For a 40 MB database
-file the timing on a 2.3 Core Duo are as follows (time in seconds):</p>
-
-<lines>
-1.3 : load data from file to string
-6.1 : convert string into tree
-5.3 : saving in file using xmlsave
-6.8 : converting to string using xml.tostring
-3.6 : saving converted string in file
-</lines>
-<p>Beware, these were timing with the old routine but measurements will not be that
-much different I guess.</p>
---ldx]]--
-- maybe this will move to lxml-xml
@@ -8054,10 +8828,7 @@ xml.newhandlers = newhandlers
xml.serialize = serialize
xml.tostring = xmltostring
---[[ldx--
-<p>The next function operated on the content only and needs a handle function
-that accepts a string.</p>
---ldx]]--
+
local function xmlstring(e,handle)
if not handle or (e.special and e.tg ~= "@rt@") then
@@ -8076,9 +8847,7 @@ end
xml.string = xmlstring
---[[ldx--
-<p>A few helpers:</p>
---ldx]]--
+
function xml.settings(e)
@@ -8122,11 +8891,7 @@ function xml.name(root)
end
end
---[[ldx--
-<p>The next helper erases an element but keeps the table as it is,
-and since empty strings are not serialized (effectively) it does
-not harm. Copying the table would take more time. Usage:</p>
---ldx]]--
+
function xml.erase(dt,k)
if dt then
@@ -8138,13 +8903,7 @@ function xml.erase(dt,k)
end
end
---[[ldx--
-<p>The next helper assigns a tree (or string). Usage:</p>
-<typing>
-dt[k] = xml.assign(root) or xml.assign(dt,k,root)
-</typing>
---ldx]]--
function xml.assign(dt,k,root)
if dt and k then
@@ -8157,20 +8916,14 @@ end
-- the following helpers may move
---[[ldx--
-<p>The next helper assigns a tree (or string). Usage:</p>
-<typing>
-xml.tocdata(e)
-xml.tocdata(e,"error")
-</typing>
---ldx]]--
+
function xml.tocdata(e,wrapper) -- a few more in the aux module
local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
- local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e }
+ local t = { special = true, ns = "", tg = "@cd@", at = { }, rn = "", dt = { whatever }, __p__ = e }
setmetatable(t,getmetatable(e))
e.dt = { t }
end
@@ -8225,7 +8978,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['lxml-pth'] = {
+if not modules then modules = { } end modules ['lxml-lpt'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -8246,28 +8999,9 @@ local setmetatableindex = table.setmetatableindex
-- beware, this is not xpath ... e.g. position is different (currently) and
-- we have reverse-sibling as reversed preceding sibling
---[[ldx--
-<p>This module can be used stand alone but also inside <l n='mkiv'/> in
-which case it hooks into the tracker code. Therefore we provide a few
-functions that set the tracers. Here we overload a previously defined
-function.</p>
-<p>If I can get in the mood I will make a variant that is XSLT compliant
-but I wonder if it makes sense.</P>
---ldx]]--
-
---[[ldx--
-<p>Expecially the lpath code is experimental, we will support some of xpath, but
-only things that make sense for us; as compensation it is possible to hook in your
-own functions. Apart from preprocessing content for <l n='context'/> we also need
-this module for process management, like handling <l n='ctx'/> and <l n='rlx'/>
-files.</p>
-
-<typing>
-a/b/c /*/c
-a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
-a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
-</typing>
---ldx]]--
+
+
+
local trace_lpath = false if trackers then trackers.register("xml.path", function(v) trace_lpath = v end) end
local trace_lparse = false if trackers then trackers.register("xml.parse", function(v) trace_lparse = v end) end
@@ -8275,11 +9009,7 @@ local trace_lprofile = false if trackers then trackers.register("xml.profile",
local report_lpath = logs.reporter("xml","lpath")
---[[ldx--
-<p>We've now arrived at an interesting part: accessing the tree using a subset
-of <l n='xpath'/> and since we're not compatible we call it <l n='lpath'/>. We
-will explain more about its usage in other documents.</p>
---ldx]]--
+
local xml = xml
@@ -8731,14 +9461,23 @@ local lp_builtin = P (
-- for the moment we keep namespaces with attributes
local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])")
-local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end)
-local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end)
+
+-- lp_fastpos_p = (P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end
+-- lp_fastpos_n = (P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end
+
+lp_fastpos_p = P("+")^0 * R("09")^1 * P(-1) / "l==%0"
+lp_fastpos_n = P("-") * R("09")^1 * P(-1) / "(%0<0 and (#list+%0==l))"
+
local lp_fastpos = lp_fastpos_n + lp_fastpos_p
+
local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
-local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
- return t .. "("
-end
+-- local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
+-- return t .. "("
+-- end
+
+-- local lp_lua_function = (R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / "%0("
+local lp_lua_function = Cs((R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(")) / "%0"
local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
if expressions[t] then
@@ -9254,9 +9993,7 @@ end
xml.applylpath = applylpath -- takes a table as first argment, which is what xml.filter will do
---[[ldx--
-<p>This is the main filter function. It returns whatever is asked for.</p>
---ldx]]--
+
function xml.filter(root,pattern) -- no longer funny attribute handling here
return applylpath(root,pattern)
@@ -9354,12 +10091,12 @@ xml.selection = selection -- new method, simple handle
-- generic function finalizer (independant namespace)
-local function dofunction(collected,fnc)
+local function dofunction(collected,fnc,...)
if collected then
local f = functions[fnc]
if f then
for c=1,#collected do
- f(collected[c])
+ f(collected[c],...)
end
else
report_lpath("unknown function '%s'",fnc)
@@ -9460,21 +10197,7 @@ expressions.tag = function(e,n) -- only tg
end
end
---[[ldx--
-<p>Often using an iterators looks nicer in the code than passing handler
-functions. The <l n='lua'/> book describes how to use coroutines for that
-purpose (<url href='http://www.lua.org/pil/9.3.html'/>). This permits
-code like:</p>
-<typing>
-for r, d, k in xml.elements(xml.load('text.xml'),"title") do
- print(d[k]) -- old method
-end
-for e in xml.collected(xml.load('text.xml'),"title") do
- print(e) -- new one
-end
-</typing>
---ldx]]--
local wrap, yield = coroutine.wrap, coroutine.yield
@@ -9515,6 +10238,32 @@ function xml.inspect(collection,pattern)
end
end
+-- texy (see xfdf):
+
+local function split(e)
+ local dt = e.dt
+ if dt then
+ for i=1,#dt do
+ local dti = dt[i]
+ if type(dti) == "string" then
+ dti = gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1")
+ dti = gsub(dti,"[\n\r]+","\n\n")
+ dt[i] = dti
+ else
+ split(dti)
+ end
+ end
+ end
+ return e
+end
+
+function xml.finalizers.paragraphs(c)
+ for i=1,#c do
+ split(c[i])
+ end
+ return c
+end
+
end -- of closure
@@ -9539,13 +10288,7 @@ local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, l
lpegpatterns.xml = lpegpatterns.xml or { }
local xmlpatterns = lpegpatterns.xml
---[[ldx--
-<p>The following helper functions best belong to the <t>lxml-ini</t>
-module. Some are here because we need then in the <t>mk</t>
-document and other manuals, others came up when playing with
-this module. Since this module is also used in <l n='mtxrun'/> we've
-put them here instead of loading mode modules there then needed.</p>
---ldx]]--
+
local function xmlgsub(t,old,new) -- will be replaced
local dt = t.dt
@@ -9731,9 +10474,7 @@ function xml.processattributes(root,pattern,handle)
return collected
end
---[[ldx--
-<p>The following functions collect elements and texts.</p>
---ldx]]--
+
-- are these still needed -> lxml-cmp.lua
@@ -9772,9 +10513,7 @@ function xml.collect_tags(root, pattern, nonamespace)
end
end
---[[ldx--
-<p>We've now arrived at the functions that manipulate the tree.</p>
---ldx]]--
+
local no_root = { no_root = true }
@@ -10160,9 +10899,7 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
end
---[[ldx--
-<p>Helper (for q2p).</p>
---ldx]]--
+
function xml.cdatatotext(e)
local dt = e.dt
@@ -10259,9 +10996,7 @@ end
-- xml.addentitiesdoctype(x,"hexadecimal")
-- print(x)
---[[ldx--
-<p>Here are a few synonyms.</p>
---ldx]]--
+
xml.all = xml.each
xml.insert = xml.insertafter
@@ -10852,7 +11587,7 @@ local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string
local concat = table.concat
local next, type = next, type
-local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
+local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
@@ -11202,12 +11937,14 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
for s in gmatch(str,"[^,]+") do
s = validate(s)
if s then
- n = n + 1 ; t[n] = s
+ n = n + 1
+ t[n] = s
end
end
else
for s in gmatch(str,"[^,]+") do
- n = n + 1 ; t[n] = s
+ n = n + 1
+ t[n] = s
end
end
if trace_expansions then
@@ -11221,7 +11958,7 @@ end
-- We could make the previous one public.
local function validate(s)
- s = collapsepath(s) -- already keeps the //
+ s = collapsepath(s) -- already keeps the trailing / and //
return s ~= "" and not find(s,"^!*unset/*$") and s
end
@@ -11559,7 +12296,7 @@ local resolvers = resolvers
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
-local fileextname = file.extname
+local suffixonly = file.suffixonly
local formats = allocate()
local suffixes = allocate()
@@ -11814,7 +12551,7 @@ function resolvers.formatofvariable(str)
end
function resolvers.formatofsuffix(str) -- of file
- return suffixmap[fileextname(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
+ return suffixmap[suffixonly(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
end
function resolvers.variableofformat(str)
@@ -11826,7 +12563,7 @@ function resolvers.variableofformatorsuffix(str)
if v then
return v
end
- v = suffixmap[fileextname(str)]
+ v = suffixmap[suffixonly(str)]
if v then
return formats[v]
end
@@ -11847,21 +12584,7 @@ if not modules then modules = { } end modules ['data-tmp'] = {
license = "see context related readme files"
}
---[[ldx--
-<p>This module deals with caching data. It sets up the paths and
-implements loaders and savers for tables. Best is to set the
-following variable. When not set, the usual paths will be
-checked. Personally I prefer the (users) temporary path.</p>
-
-</code>
-TEXMFCACHE=$TMP;$TEMP;$TMPDIR;$TEMPDIR;$HOME;$TEXMFVAR;$VARTEXMF;.
-</code>
-<p>Currently we do no locking when we write files. This is no real
-problem because most caching involves fonts and the chance of them
-being written at the same time is small. We also need to extend
-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
@@ -12396,11 +13119,12 @@ local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local filedirname = file.dirname
local filebasename = file.basename
-local fileextname = file.extname
+local suffixonly = file.suffixonly
local filejoin = file.join
local collapsepath = file.collapsepath
local joinpath = file.joinpath
local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -12424,7 +13148,7 @@ resolvers.cacheversion = '1.0.1'
resolvers.configbanner = ''
resolvers.homedir = environment.homedir
resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" }
-resolvers.luacnfname = 'texmfcnf.lua'
+resolvers.luacnfname = "texmfcnf.lua"
resolvers.luacnfstate = "unknown"
-- The web2c tex binaries as well as kpse have built in paths for the configuration
@@ -12696,7 +13420,7 @@ end
local function identify_configuration_files()
local specification = instance.specification
if #specification == 0 then
- local cnfspec = getenv('TEXMFCNF')
+ local cnfspec = getenv("TEXMFCNF")
if cnfspec == "" then
cnfspec = resolvers.luacnfspec
resolvers.luacnfstate = "default"
@@ -12784,7 +13508,7 @@ local function load_configuration_files()
-- we push the value into the main environment (osenv) so
-- that it takes precedence over the default one and therefore
-- also over following definitions
- resolvers.setenv('TEXMFCNF',cnfspec) -- resolves prefixes
+ resolvers.setenv("TEXMFCNF",cnfspec) -- resolves prefixes
-- we now identify and load the specified configuration files
instance.specification = { }
identify_configuration_files()
@@ -12832,10 +13556,11 @@ end
local function locate_file_databases()
-- todo: cache:// and tree:// (runtime)
- local texmfpaths = resolvers.expandedpathlist('TEXMF')
+ local texmfpaths = resolvers.expandedpathlist("TEXMF")
if #texmfpaths > 0 then
for i=1,#texmfpaths do
local path = collapsepath(texmfpaths[i])
+ path = gsub(path,"/+$","") -- in case $HOME expands to something with a trailing /
local stripped = lpegmatch(inhibitstripper,path) -- the !! thing
if stripped ~= "" then
local runtime = stripped == path
@@ -12964,9 +13689,9 @@ function resolvers.prependhash(type,name,cache)
end
function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash
- local t = resolvers.splitpath(getenv('TEXMF'))
+ local t = resolvers.splitpath(getenv("TEXMF")) -- okay?
insert(t,1,specification)
- local newspec = concat(t,";")
+ local newspec = concat(t,",") -- not ;
if instance.environment["TEXMF"] then
instance.environment["TEXMF"] = newspec
elseif instance.variables["TEXMF"] then
@@ -13041,14 +13766,19 @@ function resolvers.resetextrapath()
end
function resolvers.registerextrapath(paths,subpaths)
+ paths = settings_to_array(paths)
+ subpaths = settings_to_array(subpaths)
local ep = instance.extra_paths or { }
local oldn = #ep
local newn = oldn
- if paths and paths ~= "" then
- if subpaths and subpaths ~= "" then
- for p in gmatch(paths,"[^,]+") do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
+ local nofpaths = #paths
+ local nofsubpaths = #subpaths
+ if nofpaths > 0 then
+ if nofsubpaths > 0 then
+ for i=1,nofpaths do
+ local p = paths[i]
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
local ps = p .. "/" .. s
if not done[ps] then
newn = newn + 1
@@ -13058,7 +13788,8 @@ function resolvers.registerextrapath(paths,subpaths)
end
end
else
- for p in gmatch(paths,"[^,]+") do
+ for i=1,nofpaths do
+ local p = paths[i]
if not done[p] then
newn = newn + 1
ep[newn] = resolvers.cleanpath(p)
@@ -13066,10 +13797,10 @@ function resolvers.registerextrapath(paths,subpaths)
end
end
end
- elseif subpaths and subpaths ~= "" then
+ elseif nofsubpaths > 0 then
for i=1,oldn do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
local ps = ep[i] .. "/" .. s
if not done[ps] then
newn = newn + 1
@@ -13147,18 +13878,21 @@ function resolvers.expandedpathlist(str)
return { }
elseif instance.savelists then
str = lpegmatch(dollarstripper,str)
- if not instance.lists[str] then -- cached
- local lst = made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
- instance.lists[str] = expandedpathfromlist(lst)
- end
- return instance.lists[str]
+ local lists = instance.lists
+ local lst = lists[str]
+ if not lst then
+ local l = made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ lst = expandedpathfromlist(l)
+ lists[str] = lst
+ end
+ return lst
else
local lst = resolvers.splitpath(resolvers.expansion(str))
return made_list(instance,expandedpathfromlist(lst))
end
end
-function resolvers.expandedpathlistfromvariable(str) -- brrr
+function resolvers.expandedpathlistfromvariable(str) -- brrr / could also have cleaner ^!! /$ //
str = lpegmatch(dollarstripper,str)
local tmp = resolvers.variableofformatorsuffix(str)
return resolvers.expandedpathlist(tmp ~= "" and tmp or str)
@@ -13315,7 +14049,7 @@ local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
local collect_instance_files
local function find_analyze(filename,askedformat,allresults)
- local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ local filetype, wantedfiles, ext = '', { }, suffixonly(filename)
-- too tricky as filename can be bla.1.2.3:
--
-- if not suffixmap[ext] then
@@ -13393,7 +14127,7 @@ local function find_qualified(filename,allresults) -- this one will be split too
if trace_detail then
report_resolving("locating qualified file '%s'", filename)
end
- local forcedname, suffix = "", fileextname(filename)
+ local forcedname, suffix = "", suffixonly(filename)
if suffix == "" then -- why
local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
if format_suffixes then
@@ -14063,6 +14797,8 @@ local gsub = string.gsub
local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+local joinpath, basename, dirname = file.join, file.basename, file.dirname
+local getmetatable, rawset, type = getmetatable, rawset, type
-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
@@ -14104,28 +14840,43 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
+ return cleanpath(basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.dirname((fullname ~= "" and fullname) or str))
+ return cleanpath(dirname((fullname ~= "" and fullname) or str))
end
prefixes.selfautoloc = function(str)
- return cleanpath(file.join(getenv('SELFAUTOLOC'),str))
+ return cleanpath(joinpath(getenv('SELFAUTOLOC'),str))
end
prefixes.selfautoparent = function(str)
- return cleanpath(file.join(getenv('SELFAUTOPARENT'),str))
+ return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str))
end
prefixes.selfautodir = function(str)
- return cleanpath(file.join(getenv('SELFAUTODIR'),str))
+ return cleanpath(joinpath(getenv('SELFAUTODIR'),str))
end
prefixes.home = function(str)
- return cleanpath(file.join(getenv('HOME'),str))
+ return cleanpath(joinpath(getenv('HOME'),str))
+end
+
+local function toppath()
+ local pathname = dirname(inputstack[#inputstack] or "")
+ if pathname == "" then
+ return "."
+ else
+ return pathname
+ end
+end
+
+resolvers.toppath = toppath
+
+prefixes.toppath = function(str)
+ return cleanpath(joinpath(toppath(),str))
end
prefixes.env = prefixes.environment
@@ -14161,6 +14912,8 @@ function resolvers.resetresolve(str)
resolved, abstract = { }, { }
end
+-- todo: use an lpeg (see data-lua for !! / stripper)
+
local function resolve(str) -- use schemes, this one is then for the commandline only
if type(str) == "table" then
local t = { }
@@ -14186,7 +14939,7 @@ end
resolvers.resolve = resolve
resolvers.unresolve = unresolve
-if os.uname then
+if type(os.uname) == "function" then
for k, v in next, os.uname() do
if not prefixes[k] then
@@ -14198,11 +14951,17 @@ end
if os.type == "unix" then
+ -- We need to distringuish between a prefix and something else : so we
+ -- have a special repath variant for linux. Also, when a new prefix is
+ -- defined, we need to remake the matcher.
+
local pattern
local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
local colon = P(":")
- local p
for k, v in table.sortedpairs(prefixes) do
if p then
p = P(k) + p
@@ -14211,9 +14970,6 @@ if os.type == "unix" then
end
end
pattern = Cs((p * colon + colon/";" + P(1))^0)
- if t then
- t[k] = v
- end
end
makepattern()
@@ -14424,18 +15180,7 @@ local trace_cache = false trackers.register("resolvers.cache", functi
local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
---[[ldx--
-<p>Once we found ourselves defining similar cache constructs
-several times, containers were introduced. Containers are used
-to collect tables in memory and reuse them when possible based
-on (unique) hashes (to be provided by the calling function).</p>
-
-<p>Caching to disk is disabled by default. Version numbers are
-stored in the saved table which makes it possible to change the
-table structures without bothering about the disk cache.</p>
-<p>Examples of usage can be found in the font related code.</p>
---ldx]]--
containers = containers or { }
local containers = containers
@@ -14670,11 +15415,7 @@ local trace_locating = false trackers.register("resolvers.locating", function(v
local report_zip = logs.reporter("resolvers","zip")
--- zip:///oeps.zip?name=bla/bla.tex
--- zip:///oeps.zip?tree=tex/texmf-local
--- zip:///texmf.zip?tree=/tex/texmf
--- zip:///texmf.zip?tree=/tex/texmf-local
--- zip:///texmf-mine.zip?tree=/tex/texmf-projects
+
local resolvers = resolvers
@@ -14999,7 +15740,7 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-crl'] = {
+if not modules then modules = { } end modules ['data-sch'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -15007,60 +15748,199 @@ if not modules then modules = { } end modules ['data-crl'] = {
license = "see context related readme files"
}
--- this one is replaced by data-sch.lua --
+local loadstring = loadstring
+local gsub, concat, format = string.gsub, table.concat, string.format
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
-local gsub = string.gsub
+local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end)
+local report_schemes = logs.reporter("resolvers","schemes")
-local resolvers = resolvers
+local http = require("socket.http")
+local ltn12 = require("ltn12")
-local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+local resolvers = resolvers
+local schemes = resolvers.schemes or { }
+resolvers.schemes = schemes
+
+local cleaners = { }
+schemes.cleaners = cleaners
+
+local threshold = 24 * 60 * 60
+
+directives.register("schemes.threshold", function(v) threshold = tonumber(v) or threshold end)
+
+function cleaners.none(specification)
+ return specification.original
+end
+
+function cleaners.strip(specification)
+ return (gsub(specification.original,"[^%a%d%.]+","-")) -- so we keep periods
+end
+
+function cleaners.md5(specification)
+ return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
+end
+
+local cleaner = cleaners.strip
+
+directives.register("schemes.cleanmethod", function(v) cleaner = cleaners[v] or cleaners.strip end)
+
+function resolvers.schemes.cleanname(specification)
+ local hash = cleaner(specification)
+ if trace_schemes then
+ report_schemes("hashing %s to %s",specification.original,hash)
+ end
+ return hash
+end
-resolvers.curl = resolvers.curl or { }
-local curl = resolvers.curl
+local cached, loaded, reused, thresholds, handlers = { }, { }, { }, { }, { }
-local cached = { }
+local function runcurl(name,cachename) -- we use sockets instead or the curl library when possible
+ local command = "curl --silent --create-dirs --output " .. cachename .. " " .. name
+ os.spawn(command)
+end
-local function runcurl(specification)
+local function fetch(specification)
local original = specification.original
- -- local scheme = specification.scheme
- local cleanname = gsub(original,"[^%a%d%.]+","-")
- local cachename = caches.setfirstwritablefile(cleanname,"curl")
+ local scheme = specification.scheme
+ local cleanname = schemes.cleanname(specification)
+ local cachename = caches.setfirstwritablefile(cleanname,"schemes")
if not cached[original] then
- if not io.exists(cachename) then
+ statistics.starttiming(schemes)
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > (thresholds[protocol] or threshold)) then
cached[original] = cachename
- local command = "curl --silent --create-dirs --output " .. cachename .. " " .. original
- os.spawn(command)
+ local handler = handlers[scheme]
+ if handler then
+ if trace_schemes then
+ report_schemes("fetching '%s', protocol '%s', method 'built-in'",original,scheme)
+ end
+ logs.flush()
+ handler(specification,cachename)
+ else
+ if trace_schemes then
+ report_schemes("fetching '%s', protocol '%s', method 'curl'",original,scheme)
+ end
+ logs.flush()
+ runcurl(original,cachename)
+ end
end
if io.exists(cachename) then
cached[original] = cachename
+ if trace_schemes then
+ report_schemes("using cached '%s', protocol '%s', cachename '%s'",original,scheme,cachename)
+ end
else
cached[original] = ""
+ if trace_schemes then
+ report_schemes("using missing '%s', protocol '%s'",original,scheme)
+ end
+ end
+ loaded[scheme] = loaded[scheme] + 1
+ statistics.stoptiming(schemes)
+ else
+ if trace_schemes then
+ report_schemes("reusing '%s', protocol '%s'",original,scheme)
end
+ reused[scheme] = reused[scheme] + 1
end
return cached[original]
end
--- old code: we could be cleaner using specification (see schemes)
-
local function finder(specification,filetype)
- return resolvers.methodhandler("finders",runcurl(specification),filetype)
+ return resolvers.methodhandler("finders",fetch(specification),filetype)
end
local opener = openers.file
local loader = loaders.file
-local function install(scheme)
- finders[scheme] = finder
- openers[scheme] = opener
- loaders[scheme] = loader
+local function install(scheme,handler,newthreshold)
+ handlers [scheme] = handler
+ loaded [scheme] = 0
+ reused [scheme] = 0
+ finders [scheme] = finder
+ openers [scheme] = opener
+ loaders [scheme] = loader
+ thresholds[scheme] = newthreshold or threshold
end
-resolvers.curl.install = install
+schemes.install = install
+
+local function http_handler(specification,cachename)
+ local tempname = cachename .. ".tmp"
+ local f = io.open(tempname,"wb")
+ local status, message = http.request {
+ url = specification.original,
+ sink = ltn12.sink.file(f)
+ }
+ if not status then
+ os.remove(tempname)
+ else
+ os.remove(cachename)
+ os.rename(tempname,cachename)
+ end
+ return cachename
+end
-install('http')
-install('https')
+install('http',http_handler)
+install('https') -- see pod
install('ftp')
+statistics.register("scheme handling time", function()
+ local l, r, nl, nr = { }, { }, 0, 0
+ for k, v in table.sortedhash(loaded) do
+ if v > 0 then
+ nl = nl + 1
+ l[nl] = k .. ":" .. v
+ end
+ end
+ for k, v in table.sortedhash(reused) do
+ if v > 0 then
+ nr = nr + 1
+ r[nr] = k .. ":" .. v
+ end
+ end
+ local n = nl + nr
+ if n > 0 then
+ l = nl > 0 and concat(l) or "none"
+ r = nr > 0 and concat(r) or "none"
+ return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
+ statistics.elapsedtime(schemes), n, threshold, l, r)
+ else
+ return nil
+ end
+end)
+
+-- We provide a few more helpers:
+
+----- http = require("socket.http")
+local httprequest = http.request
+local toquery = url.toquery
+
+-- local function httprequest(url)
+-- return os.resultof(format("curl --silent %q", url))
+-- end
+
+local function fetchstring(url,data)
+ local q = data and toquery(data)
+ if q then
+ url = url .. "?" .. q
+ end
+ local reply = httprequest(url)
+ return reply -- just one argument
+end
+
+schemes.fetchstring = fetchstring
+
+function schemes.fetchtable(url,data)
+ local reply = fetchstring(url,data)
+ if reply then
+ local s = loadstring("return " .. reply)
+ if s then
+ return s()
+ end
+ end
+end
+
end -- of closure
@@ -15074,170 +15954,199 @@ if not modules then modules = { } end modules ['data-lua'] = {
license = "see context related readme files"
}
--- some loading stuff ... we might move this one to slot 2 depending
--- on the developments (the loaders must not trigger kpse); we could
--- of course use a more extensive lib path spec
+-- We overload the regular loader. We do so because we operate mostly in
+-- tds and use our own loader code. Alternatively we could use a more
+-- extensive definition of package.path and package.cpath but even then
+-- we're not done. Also, we now have better tracing.
+--
+-- -- local mylib = require("libtest")
+-- -- local mysql = require("luasql.mysql")
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local concat = table.concat
+
+local trace_libraries = false
+
+trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+trackers.register("resolvers.locating", function(v) trace_libraries = v end)
local report_libraries = logs.reporter("resolvers","libraries")
local gsub, insert = string.gsub, table.insert
+local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
local unpack = unpack or table.unpack
+local is_readable = file.is_readable
local resolvers, package = resolvers, package
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
-local clibformats = { 'lib' }
-
-local _path_, libpaths, _cpath_, clibpaths
-
-function package.libpaths()
- if not _path_ or package.path ~= _path_ then
- _path_ = package.path
- libpaths = file.splitpath(_path_,";")
+local libsuffixes = { 'tex', 'lua' }
+local clibsuffixes = { 'lib' }
+local libformats = { 'TEXINPUTS', 'LUAINPUTS' }
+local clibformats = { 'CLUAINPUTS' }
+
+local libpaths = nil
+local clibpaths = nil
+local libhash = { }
+local clibhash = { }
+local libextras = { }
+local clibextras = { }
+
+local pattern = Cs(P("!")^0 / "" * (P("/") * P(-1) / "/" + P("/")^1 / "/" + 1)^0)
+
+local function cleanpath(path) --hm, don't we have a helper for this?
+ return resolvers.resolve(lpegmatch(pattern,path))
+end
+
+local function getlibpaths()
+ if not libpaths then
+ libpaths = { }
+ for i=1,#libformats do
+ local paths = resolvers.expandedpathlistfromvariable(libformats[i])
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not libhash[path] then
+ libpaths[#libpaths+1] = path
+ libhash[path] = true
+ end
+ end
+ end
end
return libpaths
end
-function package.clibpaths()
- if not _cpath_ or package.cpath ~= _cpath_ then
- _cpath_ = package.cpath
- clibpaths = file.splitpath(_cpath_,";")
+local function getclibpaths()
+ if not clibpaths then
+ clibpaths = { }
+ for i=1,#clibformats do
+ local paths = resolvers.expandedpathlistfromvariable(clibformats[i])
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not clibhash[path] then
+ clibpaths[#clibpaths+1] = path
+ clibhash[path] = true
+ end
+ end
+ end
end
return clibpaths
end
-local function thepath(...)
- local t = { ... } t[#t+1] = "?.lua"
- local path = file.join(unpack(t))
- if trace_locating then
- report_libraries("! appending '%s' to 'package.path'",path)
+package.libpaths = getlibpaths
+package.clibpaths = getclibpaths
+
+function package.extralibpath(...)
+ local paths = { ... }
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not libhash[path] then
+ if trace_libraries then
+ report_libraries("! extra lua path '%s'",path)
+ end
+ libextras[#libextras+1] = path
+ libpaths[#libpaths +1] = path
+ end
end
- return path
end
-local p_libpaths, a_libpaths = { }, { }
-
-function package.appendtolibpath(...)
- insert(a_libpath,thepath(...))
+function package.extraclibpath(...)
+ local paths = { ... }
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not clibhash[path] then
+ if trace_libraries then
+ report_libraries("! extra lib path '%s'",path)
+ end
+ clibextras[#clibextras+1] = path
+ clibpaths[#clibpaths +1] = path
+ end
+ end
end
-function package.prependtolibpath(...)
- insert(p_libpaths,1,thepath(...))
+if not package.loaders[-2] then
+ -- use package-path and package-cpath
+ package.loaders[-2] = package.loaders[2]
end
--- beware, we need to return a loadfile result !
+local function loadedaslib(resolved,rawname)
+ return package.loadlib(resolved,"luaopen_" .. gsub(rawname,"%.","_"))
+end
-local function loaded(libpaths,name,simple)
- for i=1,#libpaths do -- package.path, might become option
- local libpath = libpaths[i]
- local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
+local function loadedbylua(name)
+ if trace_libraries then
+ report_libraries("! locating %q using normal loader",name)
end
+ local resolved = package.loaders[-2](name)
end
-package.loaders[2] = function(name) -- was [#package.loaders+1]
- 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
+local function loadedbyformat(name,rawname,suffixes,islib)
+ if trace_libraries then
+ report_libraries("! locating %q as %q using formats %q",rawname,name,concat(suffixes))
end
- for i=1,#libformats do
- local format = libformats[i]
+ for i=1,#suffixes do -- so we use findfile and not a lookup loop
+ local format = suffixes[i]
local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
+ if trace_libraries then
+ report_libraries("! checking for %q' using format %q",name,format)
end
if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
+ if trace_libraries then
+ report_libraries("! lib %q located on %q",name,resolved)
end
- return loadfile(resolved)
- end
- end
- -- libpaths
- local libpaths, clibpaths = package.libpaths(), package.clibpaths()
- local simple = gsub(name,"%.lua$","")
- local simple = gsub(simple,"%.","/")
- local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple)
- if resolved then
- return resolved
- end
- --
- local libname = file.addsuffix(simple,os.libsuffix)
- for i=1,#clibformats do
- -- better have a dedicated loop
- local format = clibformats[i]
- local paths = resolvers.expandedpathlistfromvariable(format)
- for p=1,#paths do
- local path = paths[p]
- local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
- end
- return package.loadlib(resolved,name)
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
end
end
end
- for i=1,#clibpaths do -- package.path, might become option
- local libpath = clibpaths[i]
- local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
+end
+
+local function loadedbypath(name,rawname,paths,islib,what)
+ if trace_libraries then
+ report_libraries("! locating %q as %q on %q paths",rawname,name,what)
+ end
+ for p=1,#paths do
+ local path = paths[p]
+ local resolved = file.join(path,name)
+ if trace_libraries then -- mode detail
+ report_libraries("! checking for %q using %q path %q",name,what,path)
end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
+ if is_readable(resolved) then
+ if trace_libraries then
+ report_libraries("! lib %q located on %q",name,resolved)
+ end
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
end
- return package.loadlib(resolved,name)
- end
- end
- -- just in case the distribution is messed up
- if trace_loading then -- more detail
- report_libraries("! checking for '%s' using 'luatexlibs': '%s'",name)
- end
- local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
- if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
end
- return loadfile(resolved)
- end
- if trace_locating then
- report_libraries('? unable to locate lib: %s',name)
end
--- return "unable to locate " .. name
end
-resolvers.loadlualib = require
-
--- -- -- --
+local function notloaded(name)
+ if trace_libraries then
+ report_libraries("? unable to locate library %q",name)
+ end
+end
-package.obsolete = package.obsolete or { }
+package.loaders[2] = function(name)
+ local thename = gsub(name,"%.","/")
+ local luaname = file.addsuffix(thename,"lua")
+ local libname = file.addsuffix(thename,os.libsuffix)
+ return
+ loadedbyformat(luaname,name,libsuffixes, false)
+ or loadedbyformat(libname,name,clibsuffixes, true)
+ or loadedbypath (luaname,name,getlibpaths (),false,"lua")
+ or loadedbypath (luaname,name,getclibpaths(),false,"lua")
+ or loadedbypath (libname,name,getclibpaths(),true, "lib")
+ or loadedbylua (name)
+ or notloaded (name)
+end
-package.append_libpath = appendtolibpath -- will become obsolete
-package.prepend_libpath = prependtolibpath -- will become obsolete
+-- package.loaders[3] = nil
+-- package.loaders[4] = nil
-package.obsolete.append_libpath = appendtolibpath -- will become obsolete
-package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+resolvers.loadlualib = require
end -- of closure
@@ -15707,7 +16616,6 @@ function environment.make_format(name)
end
function environment.run_format(name,data,more)
- -- hm, rather old code here; we can now use the file.whatever functions
if name and name ~= "" then
local barename = file.removesuffix(name)
local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
@@ -15737,6 +16645,129 @@ end
end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['util-tpl'] = {
+ 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"
+}
+
+-- This is experimental code. Coming from dos and windows, I've always used %whatever%
+-- as template variables so let's stick to it. After all, it's easy to parse and stands
+-- out well. A double %% is turned into a regular %.
+
+utilities.templates = utilities.templates or { }
+local templates = utilities.templates
+
+local trace_template = false trackers.register("templates.trace",function(v) trace_template = v end)
+local report_template = logs.reporter("template")
+
+local format = string.format
+local P, C, Cs, Carg, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.Carg, lpeg.match
+
+-- todo: make installable template.new
+
+local replacer
+
+local function replacekey(k,t,recursive)
+ local v = t[k]
+ if not v then
+ if trace_template then
+ report_template("unknown key %q",k)
+ end
+ return ""
+ else
+ if trace_template then
+ report_template("setting key %q to value %q",k,v)
+ end
+ if recursive then
+ return lpegmatch(replacer,v,1,t)
+ else
+ return v
+ end
+ end
+end
+
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local escapers = {
+ lua = function(s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local function replacekeyunquoted(s,t,how,recurse) -- ".. \" "
+ local escaper = how and escapers[how] or escapers.lua
+ return escaper(replacekey(s,t,recurse))
+end
+
+local single = P("%") -- test %test% test : resolves test
+local double = P("%%") -- test 10%% test : %% becomes %
+local lquoted = P("%[") -- test %[test]" test : resolves test with escaped "'s
+local rquoted = P("]%") --
+
+local escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
+
+local key = nosingle * (C((1-nosingle)^1 * Carg(1) * Carg(2) * Carg(3))/replacekey) * nosingle
+local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2) * Carg(3))/replacekeyunquoted) * norquoted
+local any = P(1)
+
+ replacer = Cs((unquoted + escape + key + any)^0)
+
+local function replace(str,mapping,how,recurse)
+ if mapping then
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+ return str
+ end
+end
+
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] },'sql'))
+
+templates.replace = replace
+
+function templates.load(filename,mapping,how,recurse)
+ local data = io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+ return replace(data,mapping,how,recurse)
+ else
+ return data
+ end
+end
+
+function templates.resolve(t,mapping,how,recurse)
+ if not mapping then
+ mapping = t
+ end
+ for k, v in next, t do
+ t[k] = replace(v,mapping,how,recurse)
+ end
+ return t
+end
+
+-- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" }))
+-- inspect(utilities.templates.resolve({ one = "%two%", two = "two", three = "%three%" }))
+
+
+end -- of closure
-- end library merge
own = { } -- not local, might change
@@ -15796,7 +16827,7 @@ own.libs = { -- order can be made better
-- 'data-bin.lua',
'data-zip.lua',
'data-tre.lua',
- 'data-crl.lua',
+ 'data-sch.lua',
'data-lua.lua',
'data-aux.lua', -- updater
'data-tmf.lua',
@@ -15804,6 +16835,8 @@ own.libs = { -- order can be made better
'luat-sta.lua',
'luat-fmt.lua',
+
+ 'util-tpl.lua',
}
-- We need this hack till luatex is fixed.
@@ -15824,7 +16857,7 @@ own.path = gsub(match(own.name,"^(.+)[\\/].-$") or ".","\\","/")
local ownpath, owntree = own.path, environment and environment.ownpath or own.path
-own.list = {
+own.list = { -- predictable paths
'.',
ownpath ,
ownpath .. "/../sources", -- HH's development path
@@ -15848,7 +16881,7 @@ local function locate_libs()
local filename = pth .. "/" .. lib
local found = lfs.isfile(filename)
if found then
- package.path = package.path .. ";" .. pth .. "/?.lua" -- in case l-* does a require
+ package.path = package.path .. ";" .. pth .. "/?.lua" -- in case l-* does a require (probably obsolete)
return pth
end
end
@@ -15980,6 +17013,7 @@ local helpinfo = [[
--var-value report value of variable
--find-file report file location
--find-path report path of file
+--show-package-path report package paths
--pattern=str filter variables
]]
@@ -16093,7 +17127,8 @@ function runners.execute_script(fullname,internal,nosplit)
elseif state == 'skip' then
return true
elseif state == "run" then
- local path, name, suffix, result = file.dirname(fullname), file.basename(fullname), file.extname(fullname), ""
+ local path, name, suffix = file.splitname(fullname)
+ local result = ""
if path ~= "" then
result = fullname
elseif name then
@@ -16104,7 +17139,7 @@ function runners.execute_script(fullname,internal,nosplit)
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)
+ suffix = file.suffix(name)
end
if suffix == "" then
-- loop over known suffixes
@@ -16131,7 +17166,7 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local binary = runners.applications[file.extname(result)]
+ local binary = runners.applications[file.suffix(result)]
result = string.quoted(string.unquoted(result))
-- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
-- result = '"' .. result .. '"'
@@ -16324,7 +17359,7 @@ function resolvers.launch(str)
-- maybe we also need to test on mtxrun.launcher.suffix environment
-- variable or on windows consult the assoc and ftype vars and such
local launchers = runners.launchers[os.platform] if launchers then
- local suffix = file.extname(str) if suffix then
+ local suffix = file.suffix(str) if suffix then
local runner = launchers[suffix] if runner then
str = runner .. " " .. str
end
@@ -16383,7 +17418,7 @@ function runners.find_mtx_script(filename)
end
filename = file.addsuffix(filename,"lua")
local basename = file.removesuffix(file.basename(filename))
- local suffix = file.extname(filename)
+ local suffix = file.suffix(filename)
-- qualified path, raw name
local fullname = file.is_qualified_path(filename) and io.exists(filename) and filename
if fullname and fullname ~= "" then
@@ -16438,7 +17473,7 @@ function runners.execute_ctx_script(filename,...)
runners.register_arguments(...)
local arguments = environment.arguments_after
local fullname = runners.find_mtx_script(filename) or ""
- if file.extname(fullname) == "cld" then
+ if file.suffix(fullname) == "cld" then
-- handy in editors where we force --autopdf
report("running cld script: %s",filename)
table.insert(arguments,1,fullname)
@@ -16546,6 +17581,21 @@ function runners.timed(action)
statistics.timed(action)
end
+function runners.associate(filename)
+ os.launch(filename)
+end
+
+function runners.gethelp(filename)
+ local url = environment.argument("url")
+ if url and url ~= "" then
+ local command = string.gsub(environment.argument("command") or "unknown","^%s*\\*(.-)%s*$","%1")
+ url = utilities.templates.replace(url,{ command = command })
+ os.launch(url)
+ else
+ report("no --url given")
+ end
+end
+
-- this is a bit dirty ... first we store the first filename and next we
-- split the arguments so that we only see the ones meant for this script
-- ... later we will use the second half
@@ -16648,7 +17698,18 @@ else
end
-if e_argument("selfmerge") then
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
+
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
+
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -16671,23 +17732,25 @@ elseif e_argument("selfupdate") then
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif e_argument("ctxlua") or e_argument("internal") then
+elseif e_argument("show-package-path") or e_argument("show-package-paths") then
- -- run a script by loading it (using libs)
+ local l = package.libpaths()
+ local c = package.clibpaths()
- runners.loadbase()
- ok = runners.execute_script(filename,true)
+ for i=1,#l do
+ report("package lib path %s: %s",i,l[i])
+ end
-elseif e_argument("script") or e_argument("scripts") then
+ for i=1,#c do
+ report("package clib path %s: %s",i,c[i])
+ end
- -- run a script by loading it (using libs), pass args
+elseif e_argument("ctxlua") or e_argument("internal") then
+
+ -- run a script by loading it (using libs)
runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
+ ok = runners.execute_script(filename,true)
elseif e_argument("execute") then
@@ -16715,6 +17778,14 @@ elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
+elseif e_argument("associate") then
+
+ runners.associate(filename)
+
+elseif e_argument("gethelp") then
+
+ runners.gethelp()
+
elseif e_argument("makestubs") then
-- make stubs (depricated)
@@ -16806,7 +17877,7 @@ elseif e_argument("find-path") then
elseif e_argument("expand-braces") then
- -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename
+ -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
resolvers.load("nofiles")
runners.register_arguments(filename)
diff --git a/tex/context/base/anch-bar.mkiv b/tex/context/base/anch-bar.mkiv
index 9f9770fb6..c7c6190be 100644
--- a/tex/context/base/anch-bar.mkiv
+++ b/tex/context/base/anch-bar.mkiv
@@ -58,7 +58,9 @@
\installcommandhandler \??sidebar {sidebar} \??sidebar
\newcount\c_anch_sidebars_n
-\newdimen\c_anch_sidebars_distance
+\newcount\c_anch_sidebars_current % local
+\newdimen\d_anch_sidebars_distance
+\newcount\c_anch_sidebars_level
% \setupMPvariables
% [mpos:sidebar]
@@ -67,24 +69,60 @@
% distance=5pt]
\setupsidebar
- [\c!rulethickness=2pt,
+ [\c!rulethickness=\dimexpr\bodyfontsize/6\relax, % 2pt default
\c!rulecolor=\s!black,
\c!alternative=0,
- \c!topoffset=0pt,
- \c!bottomoffset=0pt,
- \c!distance=.5\bodyfontsize]
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!distance=.5\bodyfontsize,
+ \c!level=,
+ \c!leftmargindistance=\zeropoint]
\let\setupsidebars\setupsidebar
\unexpanded\def\startsidebar
{\dosingleempty\anch_sidebars_start}
-\def\anch_sidebars_start[#1]%
+\unexpanded\def\startsidebar
+ {\dodoubleempty\anch_sidebars_start}
+
+\def\anch_sidebars_start[#1][#2]%
{\bgroup
- \def\currentsidebar{#1}%
\dontleavehmode
+ \advance\c_anch_sidebars_level\plusone
\global\advance\c_anch_sidebars_n\plusone
- \advance\c_anch_sidebars_distance\sidebarparameter\c!distance
+ \c_anch_sidebars_current\c_anch_sidebars_n\relax % relax needed
+ \doifassignmentelse{#1}
+ {\edef\currentsidebar{\the\c_anch_sidebars_level}%
+ \checksidebarparent
+ \setupcurrentsidebar[#1]}
+ {\def\currentsidebar{#1}%
+ \setupcurrentsidebar[#2]}%
+ \scratchdistance\sidebarparameter\c!distance\relax
+ \edef\m_level{\sidebarparameter\c!level}%
+ \ifx\m_level\empty
+ \ifnum\c_anch_sidebars_level=\plusone
+ \scratchdimen\sidebarparameter\c!leftmargindistance\relax
+ \ifdim\scratchdimen=\zeropoint
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \else
+ \d_anch_sidebars_distance\scratchdimen
+ \fi
+ \else
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \fi
+ \else
+ \ifnum\m_level=\plusone
+ \scratchdimen\sidebarparameter\c!leftmargindistance\relax
+ \ifdim\scratchdimen=\zeropoint
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \else
+ \d_anch_sidebars_distance\scratchdimen
+ \fi
+ \else
+ \d_anch_sidebars_distance\dimexpr\scratchdimen+\numexpr\m_level-\plusone\relax\dimexpr\scratchdistance\relax\relax
+ \fi
+ \fi
\startpositionoverlay{text-1}%
\normalexpanded{\setMPpositiongraphicrange % maybe expand in definition
{b:sidebar:\the\c_anch_sidebars_n}%
@@ -94,15 +132,17 @@
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}}%
+ topoffset=\the\dimexpr\sidebarparameter\c!topoffset,
+ bottomoffset=\the\dimexpr\sidebarparameter\c!bottomoffset,
+ distance=\the\d_anch_sidebars_distance}%
+ }%
\stoppositionoverlay
- \bpos{sidebar:\the\c_anch_sidebars_n}}
+ \bpos{sidebar:\the\c_anch_sidebars_current}%
+ \ignorespaces}
\unexpanded\def\stopsidebar
{\removelastspace
- \epos{sidebar:\the\c_anch_sidebars_n}
+ \epos{sidebar:\the\c_anch_sidebars_current}
\carryoverpar\egroup}
%D Let's keep this nice and simple (okay, we could pass the 6 variables in
@@ -121,49 +161,73 @@
\MPpositiongraphic{mpos:sidebar}{}%
\stopMPpositionmethod
-%D We now reimplement the margin rules handler defined in
-%D \type {core-rul}:
+%D We now reimplement the \MKII\ margin rules handler in a more
+%D modern way.
%D
-%D \setupmarginrules[level=5]
+%D \setupmarginrules
+%D [rulecolor=darkred,
+%D rulethickness=2pt]
%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 \setupmarginrules % sidebar
+%D [2]
+%D [rulecolor=darkblue]
%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 \startmarginrule[1]
+%D \input ward
+%D \startmarginrule[2]
+%D \input ward
+%D \startmarginrule[3]
+%D \input ward
+%D \startmarginrule[level=6,rulecolor=darkgreen]
+%D \input ward
+%D \stopmarginrule
+%D \input ward
+%D \stopmarginrule
+%D \input ward
+%D \stopmarginrule
+%D \input ward
%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 Compared to the old mechanism we now can pass settings too.
\definesidebar
[\v!margin]
- [\c!rulethickness=\@@karulethickness,
- \c!distance=\dimexpr\leftmargindistance-\@@karulethickness/2\relax]
+ [\c!leftmargindistance=\dimexpr\leftmargindistance+\sidebarparameter\c!rulethickness/2\relax]
-\definecomplexorsimple\startmarginrule
+\dorecurse{5}{\definesidebar[\v!margin:#1][\v!margin]} % let's be nice and predefine 5 levels
-\def\simplestartmarginrule
- {\complexstartmarginrule[1]}
+\unexpanded\def\setupmarginrule
+ {\dodoubleargument\anch_marginrules_setup}
-\def\complexstartmarginrule[#1]%
- {\bgroup
- \ifnum#1<\@@kalevel\relax
- \let\stopmarginrule\egroup
+\def\anch_marginrules_setup[#1][#2]%
+ {\ifsecondargument
+ \setupsidebar[\v!margin:#1][#2]%
\else
- \def\@@kadefaultwidth{#1}%
- \let\stopmarginrule\dostopmarginrule
- \normalexpanded{\startsidebar[\v!margin]}% why expanded
+ \setupsidebar[\v!margin][#1]%
\fi}
-\def\dostopmarginrule
- {\stopsidebar
- \egroup}
+\let\setupmarginrules\setupmarginrule
+
+\unexpanded\def\startmarginrule
+ {\dosingleempty\anch_marginrules_start}
+
+\unexpanded\def\startmarginrule
+ {\dosingleempty\anch_marginrules_start}
+
+\def\anch_marginrules_start[#1]% pretty inefficient checking
+ {\edef\m_anch_marginrules_kind{#1}%
+ \ifx\m_anch_marginrules_kind\empty
+ \anch_sidebars_start[\v!margin][]%
+ \else
+ \doifassignmentelse\m_anch_marginrules_kind
+ {\anch_sidebars_start[\v!margin][#1]}%
+ {\anch_marginrules_check{#1}%
+ \anch_sidebars_start[\v!margin:#1][\c!level=#1]}%
+ \fi}
+
+\def\anch_marginrules_check#1%
+ {\doifnotcommandhandler\??sidebar{\v!margin:#1}{\definesidebar[\v!margin:#1][\v!margin]}}
+
+\let\stopmarginrule\stopsidebar
\protect \endinput
diff --git a/tex/context/base/anch-bck.mkvi b/tex/context/base/anch-bck.mkvi
index 8ec056468..79e42dc0a 100644
--- a/tex/context/base/anch-bck.mkvi
+++ b/tex/context/base/anch-bck.mkvi
@@ -276,7 +276,7 @@
\kern\textbackgroundskip\nobreak
\fi \fi
\nobreak
- \vskip-\dimexpr\lineheight+\parskip\relax
+ \vskip-\dimexpr\lineheight+\parskip\relax % problem: we loose the hangindent
\nobreak
\endgroup
\begingroup
@@ -298,7 +298,7 @@
\endgraf % new
\textbackgroundparameter\c!after}
-\unexpanded\def\checkpositionoverlays
+\unexpanded\def\checkpositionoverlays % overloads \relax in anch-pgr
{\ifproductionrun
\enabletextarearegistration
\enablehiddenbackground
@@ -307,7 +307,7 @@
\setuptextbackground
[\c!mp=mpos:region:draw,
- \c!method=mpos:region,
+ \c!method=mpos:region, % mpos:regionshape
\c!state=\v!start,
\c!location=\v!text,
\c!leftoffset=\!!zeropoint, % 1em,
@@ -397,6 +397,14 @@
\includeMPgraphic{mpos:region:anchor} ;
\stopMPpositiongraphic
+\startMPpositiongraphic{mpos:regionshape}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset}
+ \includeMPgraphic{mpos:region:setup} ;
+ \includeMPgraphic{mpos:region:extra} ;
+ \MPgetmultishapes{\MPvar{self}}{\MPanchorid} ;
+ \includeMPgraphic{\MPvar{mp}} ;
+ \includeMPgraphic{mpos:region:anchor} ;
+\stopMPpositiongraphic
+
\startMPpositionmethod{mpos:region}
\MPpositiongraphic{mpos:region}{}%
\stopMPpositionmethod
diff --git a/tex/context/base/anch-pgr.lua b/tex/context/base/anch-pgr.lua
index bf4dcbe02..aba61794b 100644
--- a/tex/context/base/anch-pgr.lua
+++ b/tex/context/base/anch-pgr.lua
@@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['anch-pgr'] = {
-- todo: we need to clean up lists (of previous pages)
+local commands, context = commands, context
+
local format = string.format
local abs = math.abs
local concat, sort = table.concat, table.sort
@@ -47,34 +49,48 @@ end
local eps = 2
-local function add(t,x,y,last)
+local function add(t,x,y,last,direction)
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
+ if x == lx and y == ly then
+ -- quick skip
+ elseif n == 1 then
+-- if abs(lx-x) <= eps or abs(ly-y) <= eps then
+ if abs(lx-x) > eps or abs(ly-y) > eps then
+ t[n+1] = { x, y }
end
- elseif abs(ly-tm[2]) <= eps and abs(ly-y) <= eps then
- if abs(lx-x) > eps then
- tn[1] = x
+ else
+ local tm = t[n-1]
+ local px = tm[1]
+ local py = tm[2]
+if (direction == "down" and y > ly) or (direction == "up" and y < ly) then
+ -- move back from too much hang
+else
+ if abs(lx-px) <= eps and abs(lx-x) <= eps then
+ if abs(ly-y) > eps then
+ tn[2] = y
+ end
+ elseif abs(ly-py) <= 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
- elseif not last then
- t[n+1] = { x, y }
+end
end
end
end
+-- local function add(t,x,y,last)
+-- t[#t+1] = { x, y }
+-- end
+
local function finish(t)
local n = #t
if n > 1 then
@@ -109,105 +125,103 @@ end
-- todo: mark regions and free paragraphs in collected
-local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot)
+local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot,obeyhang)
-- 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
+ leftshape = { { rx, rh } } -- spikes get removed so we can start at the edge
+ rightshape = { { rw, rh } } -- even if we hang next
+ local paragraphs = r.paragraphs
+ local extending = false
+ if paragraphs then
+ for i=1,#paragraphs do
+ local p = paragraphs[i]
+ local ha = p.ha
+ if obeyhang and 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,"up")
+ add(rightshape,rw + hi,py_ph,"up")
+ add(rightshape,rw + hi,py_ph + hang,"up")
+ add(rightshape,rw, py_ph + hang,"up")
+ else
+ -- left
+ add(leftshape,rx,py_ph,"down")
+ add(leftshape,rx + hi,py_ph,"down")
+ add(leftshape,rx + hi,py_ph + hang,"down")
+ add(leftshape,rx,py_ph + hang,"down")
+ end
+ else
+ -- maybe some day
+ end
+ extending = true -- 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 hi = p.hi
- local hang = ha * (ph + pd)
+ local step = ph + pd
+ local size = #ps * step
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
+ add(leftshape,rx,py_ph,"up")
+ add(rightshape,rw,py_ph,"down")
+ for i=1,#ps do
+ local p = ps[i]
+ local l = p[1]
+ local w = p[2]
+ add(leftshape,rx + l, py_ph,"up")
+ add(rightshape,rx + l + w, py_ph,"down")
+ py_ph = py_ph - step
+ add(leftshape,rx + l, py_ph,"up")
+ add(rightshape,rx + l + w, py_ph,"down")
end
+ extending = true
+ elseif 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,"up")
+ add(rightshape,rightshape[#rightshape][1],py_ph,"down")
+ add(leftshape,rx,py_ph,"up") -- shouldn't this be py_pd
+ add(rightshape,rw,py_ph,"down") -- shouldn't this be py_pd
+ extending = false
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
+ 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,"up")
+ add(rightshape,rw,rd,"down")
+ end
return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot)
end
-local function singlepart(b,e,r,left,right)
+-- local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot,obeyhang)
+-- local leftshape = { { rx, rh }, { rx, rd } }
+-- local rightshape = { { rw, rh }, { rw, rd } }
+-- return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot)
+-- end
+
+local function singlepart(b,e,r,left,right,obeyhang)
local bx, by = b.x, b.y
local ex, ey = e.x, e.y
local rx, ry = r.x, r.y
@@ -238,7 +252,7 @@ local function singlepart(b,e,r,left,right)
}
else
area = { }
- local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,ed,bh,eh)
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,ed,bh,eh,obeyhang)
add(area,bx,bh-ry)
for i=1,#rightshapes do
local ri = rightshapes[i]
@@ -265,7 +279,7 @@ local function singlepart(b,e,r,left,right)
}
end
-local function firstpart(b,r,left,right)
+local function firstpart(b,r,left,right,obeyhang)
local bx, by = b.x, b.y
local rx, ry = r.x, r.y
local rw = rx + r.w
@@ -278,7 +292,7 @@ local function firstpart(b,r,left,right)
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)
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,rd,bh,rd,obeyhang)
add(area,bx,bh-ry)
for i=1,#rightshapes do
local ri = rightshapes[i]
@@ -302,7 +316,7 @@ local function firstpart(b,r,left,right)
}
end
-local function middlepart(r,left,right)
+local function middlepart(r,left,right,obeyhang)
local rx, ry = r.x, r.y
local rw = rx + r.w
local rh = ry + r.h
@@ -312,7 +326,7 @@ local function middlepart(r,left,right)
rw = rw - right
end
local area = { }
- local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,rd,rh,rd)
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,rd,rh,rd,obeyhang)
for i=#leftshapes,1,-1 do
local li = leftshapes[i]
add(area,li[1],li[2]-ry)
@@ -333,7 +347,7 @@ local function middlepart(r,left,right)
}
end
-local function lastpart(e,r,left,right)
+local function lastpart(e,r,left,right,obeyhang)
local ex, ey = e.x, e.y
local rx, ry = r.x, r.y
local rw = rx + r.w
@@ -347,7 +361,7 @@ local function lastpart(e,r,left,right)
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)
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,ed,rh,eh,obeyhang)
for i=1,#rightshapes do
local ri = rightshapes[i]
add(area,ri[1],ri[2]-ry)
@@ -375,7 +389,7 @@ local backgrounds = { }
graphics.backgrounds = backgrounds
-local function calculatemultipar(tag)
+local function calculatemultipar(tag,obeyhang)
local collected = jobpositions.collected
local b = collected[format("b:%s",tag)]
local e = collected[format("e:%s",tag)]
@@ -429,13 +443,13 @@ local function calculatemultipar(tag)
--
if bindex == eindex then
return {
- list = { [b.p] = { singlepart(b,e,collected[br],left,right) } },
+ list = { [b.p] = { singlepart(b,e,collected[br],left,right,obeyhang) } },
bpos = b,
epos = e,
}
else
local list = {
- [b.p] = { firstpart(b,collected[br],left,right) },
+ [b.p] = { firstpart(b,collected[br],left,right,obeyhang) },
}
for i=bindex+1,eindex-1 do
br = format("%s:%s",btag,i)
@@ -446,18 +460,18 @@ local function calculatemultipar(tag)
local p = r.p
local pp = list[p]
if pp then
- pp[#pp+1] = middlepart(r,left,right)
+ pp[#pp+1] = middlepart(r,left,right,obeyhang)
else
- list[p] = { middlepart(r,left,right) }
+ list[p] = { middlepart(r,left,right,obeyhang) }
end
end
end
local p = e.p
local pp = list[p]
if pp then
- pp[#pp+1] = lastpart(e,collected[er],left,right)
+ pp[#pp+1] = lastpart(e,collected[er],left,right,obeyhang)
else
- list[p] = { lastpart(e,collected[er],left,right) }
+ list[p] = { lastpart(e,collected[er],left,right,obeyhang) }
end
return {
list = list,
@@ -537,10 +551,10 @@ local template_d = [[
setbounds currentpicture to multibox ;
]]
-function backgrounds.fetchmultipar(n,anchor,page)
+function backgrounds.fetchmultipar(n,anchor,page,obeyhang)
local data = pbg[n]
if not data then
- data = calculatemultipar(n)
+ data = calculatemultipar(n,obeyhang)
pbg[n] = data -- can be replaced by register
-- register(data.list,n,anchor)
end
@@ -590,6 +604,10 @@ function commands.fetchmultipar(n,anchor,page)
context(backgrounds.fetchmultipar(n,anchor,page))
end
+function commands.fetchmultishape(n,anchor,page)
+ context(backgrounds.fetchmultipar(n,anchor,page,true))
+end
+
local template_a = [[
path posboxes[], posregions[] ;
numeric pospages[] ;
@@ -642,10 +660,10 @@ end
local doifelse = commands.doifelse
-function commands.doifelsemultipar(n,page)
+function commands.doifelsemultipar(n,page,obeyhang)
local data = pbg[n]
if not data then
- data = calculatemultipar(n)
+ data = calculatemultipar(n,obeyhang)
pbg[n] = data
end
if page then
diff --git a/tex/context/base/anch-pgr.mkiv b/tex/context/base/anch-pgr.mkiv
index a417d26e3..01ef25dc4 100644
--- a/tex/context/base/anch-pgr.mkiv
+++ b/tex/context/base/anch-pgr.mkiv
@@ -33,7 +33,7 @@
\installcorenamespace{positionaction}
\installcorenamespace{positioncleanup}
-\unexpanded\def\dosetpositionaction#1%
+\unexpanded\def\anch_positions_set_action#1%
{\expandafter\gdef\csname\??positionaction#1\endcsname} % nicely gobbles spaces
\unexpanded\def\doifpositionaction#1%
@@ -111,7 +111,7 @@
{\begingroup
\edef\currentpositionanchor
{\ifx\currentpositionoverlay\empty#3\else\currentpositionoverlay::\MPanchoridentifier\fi}%
- \normalexpanded{\dosetpositionaction{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}%
+ \normalexpanded{\anch_positions_set_action{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}%
\let#1\relax
\ifcsname\??positioncleanup\currentpositionanchor\endcsname
\setxvalue{\??positioncleanup\currentpositionanchor}%
@@ -140,9 +140,6 @@
\fi
\fi\fi}
-% \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}}
@@ -218,7 +215,6 @@
%D \typebuffer[graphic]
\def\MPanchoridentifier{mpa} % {mp-anchor}
-%def\MPoverlayposprefix{MO::} % not used
%D The rest of the definitions concerning such overlays may
%D look complicated,
@@ -237,8 +233,8 @@
\def\textbackgroundoverlay#1{\v!text#1}
\def\MPanchornumber {\the\realpageno}
-\def\positionoverlay % the test prevents too many redundant positions
- {\ifpositioning % in (not used) text* position layers
+\unexpanded\def\positionoverlay % the test prevents too many redundant positions
+ {\ifpositioning % in (not used) text* position layers
\expandafter\anch_positions_overlay_indeed
\else % also \iftrialtypesetting test here?
\expandafter\gobbleoneargument
@@ -269,7 +265,7 @@
\box\scratchbox
\vfill}}
-\def\positionregionoverlay % shares regions
+\unexpanded\def\positionregionoverlay % shares regions
{\ifpositioning
\expandafter\anch_positions_region_overlay_indeed
\else % also \iftrialtypesetting test here?
@@ -308,9 +304,15 @@
\expandafter\anch_positions_overlay_start_yes
\fi}
+\let\stoppositionoverlay\relax
+
\def\anch_positions_overlay_start_nop#1\stoppositionoverlay
{}
+\ifdefined\checkpositionoverlays \else \let\checkpositionoverlays\relax \fi
+
+\let\currentpositionoverlay\empty
+
\def\anch_positions_overlay_start_yes#1%
{\checkpositionoverlays
\edef\currentpositionoverlay{#1}}
@@ -318,9 +320,11 @@
\unexpanded\def\stoppositionoverlay
{\let\currentpositionoverlay\empty}
+% needs checking if still needed
+%
% \def\resetpositionoverlay#1%
-% {\dosetpositionaction{#1::\MPanchoridentifier::}{}}
-
+% {\anch_positions_set_action{#1::\MPanchoridentifier::}{}}
+%
% \def\handlepositionboxes#1#2#3%
% {\handlepositionaction\dohandlepositionboxes\with{#1}{#2}{#3}\on{#2}}
%
@@ -332,15 +336,15 @@
% \appendtoks
% \let\dohandlepositionboxes\doinsertpositionboxes % was handle ?
% \to \everyinsertpositionaction
-
-\def\docleanpositionboxes#1#2#3% pos tag setups
- {\ifnum\MPp{#1}<\realpageno \else
- \noexpand \dohandlepositionboxes{#1}{#2}{#3}% reinsert
- \fi}
-
-\appendtoks
- \let\dohandlepositionboxes\docleanpositionboxes
-\to \everycleanpositionaction
+%
+% \def\docleanpositionboxes#1#2#3% pos tag setups
+% {\ifnum\MPp{#1}<\realpageno \else
+% \noexpand \dohandlepositionboxes{#1}{#2}{#3}% reinsert
+% \fi}
+%
+% \appendtoks
+% \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
@@ -350,7 +354,7 @@
\installcorenamespace{positionmethod}
%installcorenamespace{graphicvariable}
-\newbox\positiongraphicbox
+\newbox\b_anch_positions_graphic
\def\startMPpositiongraphic % id setups
{\dodoublegroupempty\anch_positions_meta_graphic_start}
@@ -361,11 +365,11 @@
\let\stopMPpositiongraphic\relax
\def\anch_positions_meta_graphic_prepare
- {\ifcsname\??gv\currentmpvariableclass:self\endcsname \else
- \letvalue{\??gv\currentmpvariableclass:self}\currentposition
+ {\ifcsname\??graphicvariable\currentmpvariableclass:self\endcsname \else
+ \letvalue{\??graphicvariable\currentmpvariableclass:self}\currentposition
\fi
- \ifcsname\??gv\currentmpvariableclass:from\endcsname \else
- \letvalue{\??gv\currentmpvariableclass:from}\currentposition
+ \ifcsname\??graphicvariable\currentmpvariableclass:from\endcsname \else
+ \letvalue{\??graphicvariable\currentmpvariableclass:from}\currentposition
\fi}
\def\anch_positions_meta_graphic_use#1#2#3%
@@ -375,7 +379,7 @@
\startMPcode#3\stopMPcode
\endgroup}
-\def\MPpositiongraphic
+\unexpanded\def\MPpositiongraphic
{\dodoublegroupempty\anch_positions_meta_graphic_direct}
\def\anch_positions_meta_graphic_direct#1% tag setups
@@ -402,9 +406,9 @@
\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
+ \setbox\b_anch_positions_graphic\hbox{\ignorespaces\csname#1#2\endcsname\removelastspace}%
+ \smashbox\b_anch_positions_graphic
+ \box\b_anch_positions_graphic
\endgroup}
\def\anch_positions_meta_graphic_nested#1#2#3% nesting used in prikkels / pascal (might go away)
@@ -422,77 +426,77 @@
%D Simple one position graphics.
-\def\setMPpositiongraphic
- {\dotriplegroupempty\dosetMPpositiongraphic}
+\unexpanded\def\setMPpositiongraphic
+ {\dotriplegroupempty\anch_positions_meta_graphic_set}
-\def\dosetMPpositiongraphic#1#2#3% pos tag vars
+\def\anch_positions_meta_graphic_set#1#2#3% pos tag vars
{\ifx\currentpositionoverlay\empty
- \dosetpositionaction{#1}{\MPpositiongraphic{#2}{#3}}%
+ \anch_positions_set_action{#1}{\MPpositiongraphic{#2}{#3}}%
\else % silly can be one
- \handlepositiongraphics{#1}{#2}{#3}%
+ \anch_positions_meta_graphic_handle{#1}{#2}{#3}%
\fi}
-\def\handlepositiongraphics#1#2#3% combine with boxes
- {\handlepositionaction\dohandleMPpositiongraphic\with{#1}{#2}{#3}\on{#2}}
+\def\anch_positions_meta_graphic_handle#1#2#3% combine with boxes
+ {\handlepositionaction\anch_positions_meta_graphic_handle_indeed\with{#1}{#2}{#3}\on{#2}}
-\def\doinsertMPpositiongraphic#1#2#3% pos tag setups
+\def\anch_positions_meta_graphic_insert#1#2#3% pos tag setups
{\ifnum\MPp{#1}=\realpageno\relax % extra saveguard
\def\currentposition{#1}\MPpositiongraphic{#2}{#3}%
\fi}
\appendtoks
- \let\dohandleMPpositiongraphic\doinsertMPpositiongraphic
+ \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_insert
\to \everyinsertpositionaction
-\def\docleanMPpositiongraphic#1#2#3% pos tag setups
+\def\anch_positions_meta_graphic_cleanup#1#2#3% pos tag setups
{\ifnum\MPp{#1}<\realpageno \else
- \noexpand\dohandleMPpositiongraphic{#1}{#2}{#3}%
+ \noexpand\anch_positions_meta_graphic_handle_indeed{#1}{#2}{#3}%
\fi}
\appendtoks
- \let\dohandleMPpositiongraphic\docleanMPpositiongraphic
+ \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_cleanup
\to \everycleanpositionaction
%D Graphics that span two positions (beware, does not cross pages).
\unexpanded\def\setMPpositiongraphicrange
- {\doquadruplegroupempty\dosetMPpositiongraphicrange}
+ {\doquadruplegroupempty\anch_positions_meta_graphic_set_range}
-\def\dosetMPpositiongraphicrange#1#2#3#4% bpos epos tag vars
+\def\anch_positions_meta_graphic_set_range#1#2#3#4% bpos epos tag vars
{\ifx\currentpositionoverlay\empty
- \dosetpositionaction{#1}{\MPpositiongraphic{#3}{#4}}%
+ \anch_positions_set_action{#1}{\MPpositiongraphic{#3}{#4}}%
\else
- \handlepositiongraphicsrange{#1}{#2}{#3}{#4}%
+ \anch_positions_meta_graphic_handle_range{#1}{#2}{#3}{#4}%
\fi}
-\def\handlepositiongraphicsrange#1#2#3#4%
- {\handlepositionaction\dohandleMPpositiongraphicrange\with{#1}{#2}{#3}{#4}\on{#2}}
+\def\anch_positions_meta_graphic_handle_range#1#2#3#4%
+ {\handlepositionaction\anch_positions_meta_graphic_handle_range_indeed\with{#1}{#2}{#3}{#4}\on{#2}}
-\def\doinsertMPpositiongraphicrange#1#2#3#4% pos pos tag setups
+\def\anch_positions_meta_graphic_insert_range#1#2#3#4% pos pos tag setups
{\ctxcommand{doifelserangeonpage("#1","#2",\number\realpageno)}%
- {%\writestatus{YES}{#1/#2 => #3}%
- \def\currentposition{#1}%
+ {\def\currentposition{#1}%
\MPpositiongraphic{#3}{#4}}%
- {}}%\writestatus{NOP}{#1/#2 = #3}}}
+ {}}
\appendtoks
- \let\dohandleMPpositiongraphicrange\doinsertMPpositiongraphicrange
+ \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_insert_range
\to \everyinsertpositionaction
-\def\docleanMPpositiongraphicrange#1#2#3#4% pos tag setups
+\def\anch_positions_meta_graphic_cleanup_range#1#2#3#4% pos tag setups
{\ifnum\MPp{#2}<\realpageno \else
- \noexpand \dohandleMPpositiongraphicrange{#1}{#2}{#3}{#4}%
+ \noexpand \anch_positions_meta_graphic_handle_range_indeed{#1}{#2}{#3}{#4}%
\fi}
\appendtoks
- \let\dohandleMPpositiongraphicrange\docleanMPpositiongraphicrange
+ \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_cleanup_range
\to \everycleanpositionaction
-\let\dohandleMPpositiongraphicrange\gobblefourarguments
+\let\anch_positions_meta_graphic_handle_range_indeed\gobblefourarguments
% Helpers:
-\def\MPgetposboxes #1#2{\ctxcommand{fetchposboxes("#1","#2",\the\realpageno)}}
-\def\MPgetmultipars#1#2{\ctxcommand{fetchmultipar("#1","#2",\the\realpageno)}}
+\def\MPgetposboxes #1#2{\ctxcommand{fetchposboxes("#1","#2",\the\realpageno)}}
+\def\MPgetmultipars #1#2{\ctxcommand{fetchmultipar("#1","#2",\the\realpageno)}}
+\def\MPgetmultishapes#1#2{\ctxcommand{fetchmultishape("#1","#2",\the\realpageno)}}
\protect \endinput
diff --git a/tex/context/base/anch-pos.lua b/tex/context/base/anch-pos.lua
index 5d01a6e46..6fa916291 100644
--- a/tex/context/base/anch-pos.lua
+++ b/tex/context/base/anch-pos.lua
@@ -17,6 +17,8 @@ more efficient.</p>
-- 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 commands, context = commands, context
+
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
@@ -969,35 +971,35 @@ function commands.MPxywhd(id)
end
end
--- is testcase already defined? if so, then local
+local doif, doifelse = commands.doif, commands.doifelse
function commands.doifpositionelse(name)
- commands.doifelse(collected[name])
+ doifelse(collected[name])
end
function commands.doifposition(name)
- commands.doif(collected[name])
+ doif(collected[name])
end
function commands.doifpositiononpage(name,page) -- probably always realpageno
local c = collected[name]
- commands.testcase(c and c.p == page)
+ doifelse(c and c.p == page)
end
function commands.doifoverlappingelse(one,two,overlappingmargin)
- commands.testcase(overlapping(one,two,overlappingmargin))
+ doifelse(overlapping(one,two,overlappingmargin))
end
function commands.doifpositionsonsamepageelse(list,page)
- commands.testcase(onsamepage(list))
+ doifelse(onsamepage(list))
end
function commands.doifpositionsonthispageelse(list)
- commands.testcase(onsamepage(list,tostring(tex.count.realpageno)))
+ doifelse(onsamepage(list,tostring(tex.count.realpageno)))
end
function commands.doifelsepositionsused()
- commands.testcase(next(collected))
+ doifelse(next(collected))
end
commands.markcolumnbox = jobpositions.markcolumnbox
diff --git a/tex/context/base/anch-pos.mkiv b/tex/context/base/anch-pos.mkiv
index 2e13eeba2..7ecaa296e 100644
--- a/tex/context/base/anch-pos.mkiv
+++ b/tex/context/base/anch-pos.mkiv
@@ -361,9 +361,9 @@
\startcolor[blue]%
\llap{\infofont\number\c_anch_positions_paragraph}%
\vrule
- \!!width 4\onepoint
- \!!height2\onepoint
- \!!depth 2\onepoint
+ \s!width 4\onepoint
+ \s!height2\onepoint
+ \s!depth 2\onepoint
\stopcolor
\hss}}
@@ -377,7 +377,7 @@
{\smashedhbox
{#1{\infofont#2#3}%
\kern-\onepoint
- \vrule\!!width2\onepoint\!!height\halfapoint\!!depth\halfapoint}}
+ \vrule\s!width2\onepoint\s!height\halfapoint\s!depth\halfapoint}}
\unexpanded\def\anch_positions_trace_left_indeed
{\anch_positions_trace\llap\darkmagenta{\currentposition>}}
diff --git a/tex/context/base/anch-tab.mkiv b/tex/context/base/anch-tab.mkiv
index 4bdaa2ef9..2fb6938a2 100644
--- a/tex/context/base/anch-tab.mkiv
+++ b/tex/context/base/anch-tab.mkiv
@@ -13,6 +13,9 @@
\writestatus{loading}{ConTeXt Anchoring Macros / Table Extensions}
+%D This is just a playground and functionality might change or even
+%D dissappear in favour of better solutions.
+
\unprotect
\newcount\c_anch_tabs
@@ -57,23 +60,22 @@
\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 Beware, the following code is somewhat weird and experimental and might be
+%D 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.
+%D The next macros extend tables and tabulation with backgrounds and position
+%D related features. Areas are specified with symbolic names, and symbolic
+%D references to the graphics involved. Each table has its own namespace.
\newconditional\tablehaspositions
-\newcount\noftabpositions
-\newtoks \posXCtoks
+\newcount \noftabpositions
+\newtoks \posXCtoks
-\def\dotablebpos{\bpos}
-\def\dotableepos{\epos}
+\def\anch_tabulate_bpos{\bpos}
+\def\anch_tabulate_epos{\epos}
\installcorenamespace{positiontables}
@@ -85,74 +87,80 @@
\let\tabulatepos\tablepos
-\def\dodododoGSC[#1:#2]%
- {\remappositionframed{#2}{\tbPOSprefix#1}%
- \dotablebpos{\tbPOSprefix#1}%
- \doglobal\appendtoks\@EA\dotableepos\@EA{\tbPOSprefix#1}\to\posXCtoks}
+\unexpanded\def\tbXC {\dosingleempty\anch_tables_XC }
+\unexpanded\def\tbGSC{\dosingleempty\anch_tables_GSC}
+\unexpanded\def\tbGFC{\dosingleempty\anch_tables_GFC}
+\unexpanded\def\tbGTC{\dosingleempty\anch_tables_GTC}
-\def\dododoGSC[#1:#2:#3]%
- {\doglobal\appendtoks\dodododoGSC[#1:#2]\to\posXCtoks\NC}
+\def\anch_table_check_state
+ {\iftrialtypesetting
+ \global\settrue\tablehaspositions
+ \firstargumentfalse
+ \fi}
-\def\dodoGSC[#1]%
- {\def\docommand##1{\dododoGSC[##1:##1]}%
- \processcommalist[#1]\docommand}
+\def\anch_tables_XC [#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_XC [#1]\else\expandafter\fi\NC}
+\def\anch_tables_GSC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GSC[#1]\else\expandafter\NC\fi}
+\def\anch_tables_GFC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GFC[#1]\else\expandafter\NC\fi}
+\def\anch_tables_GTC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GTC[#1]\else\expandafter\NC\fi}
-\def\dodododoGFC[#1:#2:#3]%
- {\remappositionframed{#2}{\tbPOSprefix#1}%
- \dotablebpos{\tbPOSprefix#1}}
+\def\anch_tables_indeed_XC[#1]%
+ {{\let\NC\relax\processcommalist[#1]\anch_tables_step_XC}}
-\def\dododoGFC[#1]%
- {\def\docommand##1{\dodododoGFC[##1:##1]}%
- \processcommalist[#1]\docommand}
+\def\anch_tables_step_XC#1%
+ {\anch_tables_step_indeed_XC[#1]}
-\def\dodoGFC[#1]%
- {\doglobal\appendtoks\dododoGFC[#1]\to\posXCtoks\NC}
+\def\anch_tables_step_indeed_XC[#1#2]%
+ {\if#1>\anch_tables_indeed_GFC [#2:#2]\else
+ \if#1+\anch_tables_indeed_GFC [#2:#2]\else
+ \if#1<\anch_tables_indeed_GTC [#2:#2]\else
+ \if#1-\anch_tables_indeed_GTC [#2:#2]\else
+ \if#1=\anch_tables_indeed_GSC [#2:#2]\else
+ \anch_tables_indeed_GSC[#1#2:#1#2]\fi\fi\fi\fi\fi}
-\def\dododododoGTC[#1:#2]%
- {\dotableepos{\tbPOSprefix#1}}
+\def\anch_tables_indeed_GSC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GSC}
-\def\dodododoGTC[#1]%
- {\def\docommand##1{\dododododoGTC[##1:##1]}%
- \processcommalist[#1]\docommand}
+\def\anch_tables_step_GSC#1%
+ {\anch_tables_append_GSC[#1:#1]}
-\def\dododoGTC[#1]%
- {\doglobal\appendtoks\dodododoGTC[#1]\to\posXCtoks}
+\def\anch_tables_append_GSC[#1:#2:#3]%
+ {\doglobal\appendtoks\anch_tables_process_GSC[#1:#2]\to\posXCtoks\NC}
-\def\dodoGTC[#1]%
- {\doglobal\appendtoks\dododoGTC[#1]\to\posXCtoks\NC}
+\def\anch_tables_process_GSC[#1:#2]%
+ {\remappositionframed{#2}{\tbPOSprefix#1}%
+ \anch_tabulate_bpos{\tbPOSprefix#1}%
+ \doglobal\appendtoks\@EA\anch_tabulate_epos\@EA{\tbPOSprefix#1}\to\posXCtoks}
-\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\anch_tables_indeed_GFC[#1]%
+ {\doglobal\appendtoks\anch_tables_delayed_GFC[#1]\to\posXCtoks\NC}
-\def\dododoXC#1%
- {\dodododoXC[#1]}
+\def\anch_tables_delayed_GFC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GFC}
-\def\dodoXC[#1]%
- {{\let\NC\relax\processcommalist[#1]\dododoXC}}
+\def\anch_tables_step_GFC#1%
+ {\anch_tables_process_GFC[#1:#1]}
-\def\@@checktablepositionstate
- {\iftrialtypesetting
- \global\settrue\tablehaspositions
- \firstargumentfalse
- \fi}
+\def\anch_tables_process_GFC[#1:#2:#3]%
+ {\remappositionframed{#2}{\tbPOSprefix#1}%
+ \anch_tabulate_bpos{\tbPOSprefix#1}}
+
+\def\anch_tables_indeed_GTC[#1]%
+ {\doglobal\appendtoks\anch_tables_delayed_GTC[#1]\to\posXCtoks\NC}
-\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\anch_tables_delayed_GTC[#1]%
+ {\doglobal\appendtoks\anch_tables_process_GTC[#1]\to\posXCtoks}
-\def\tbGSC{\dosingleempty\doGSC}
-\def\tbGFC{\dosingleempty\doGFC}
-\def\tbGTC{\dosingleempty\doGTC}
-\def\tbXC {\dosingleempty\doXC }
+\def\anch_tables_process_GTC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GTC}
-%D The amount of code to support tables and tabulation is
-%D rather minimalistic.
+\def\anch_tables_step_GTC#1%
+ {\anch_tables_step_indeed_GTC[#1:#1]}
+
+\def\anch_tables_step_indeed_GTC[#1:#2]%
+ {\anch_tabulate_epos{\tbPOSprefix#1}}
+
+%D The amount of code to support tables and tabulation is rather
+%D minimalistic.
\let\tabulatepos\tablepos
@@ -187,31 +195,30 @@
% We need to handle paragraphs as well.
-\let\doflushtabulateepos\relax
+\let\anch_tabulate_flush_epos\relax
-\def\dotabulatebpos
+\def\anch_tabulate_bpos_indeed
{\bpos}
-\def\dotabulateepos#1%
+\def\anch_tabulate_epos_indeed#1%
{\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
\epos{#1}%
- \glet\doflushtabulateepos\relax
+ \glet\anch_tabulate_flush_epos\relax
\else
- \gdef\doflushtabulateepos{\epos{#1}}%
+ \gdef\anch_tabulate_flush_epos{\epos{#1}}%
\fi}
\def\flushtabulatesplitbox
{\box\b_tabl_tabulate
- \iftrialtypesetting\else\ifconditional\tablehaspositions\doflushtabulateepos\fi\fi}
+ \iftrialtypesetting\else\ifconditional\tablehaspositions\anch_tabulate_flush_epos\fi\fi}
\appendtoks
- \let\dotablebpos\dotabulatebpos % ?
- \let\dotableepos\dotabulateepos % ?
- \glet\doflushtabulateepos\relax
+ \let\anch_tabulate_bpos\anch_tabulate_bpos_indeed % ?
+ \let\anch_tabulate_epos\anch_tabulate_epos_indeed % ?
+ \glet\anch_tabulate_flush_epos\relax
\to \everytabulate
-%D In order to prevent potential clashes with abbreviations,
-%D postpone the mapping.
+%D In order to prevent potential clashes with abbreviations, postpone the mapping.
\appendtoks
\let\GSC\tbGSC
@@ -223,8 +230,8 @@
%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 The next example show how to provide backgrounds to table cells. First we define
+%D some framed backgrounds.
%D
%D \startbuffer
%D \definepositionframed[x][background=color,backgroundcolor=red]
@@ -244,8 +251,7 @@
%D \stoptabulate
%D \stopbuffer
%D
-%D The table itself defines three areas (a, b and~c) using
-%D these frames.
+%D The table itself defines three areas (a, b and~c) using these frames.
%D
%D \typebuffer
%D % \getbuffer
@@ -270,9 +276,8 @@
\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 In the previous example, we could have provided an overlay to the framed definition.
+%D A more direct approach is demonstrated below:
%D
%D \startbuffer
%D \def\cw#1{\color[white]{#1}}
@@ -291,8 +296,7 @@
%D
%D \typebuffer \getbuffer
%D
-%D The definition of the table looks about the same as the
-%D previous one:
+%D The definition of the table looks about the same as the previous one:
%D
%D \startbuffer
%D \starttable[|c|c|c|]
@@ -347,22 +351,26 @@
% \definepositionframed[y][background=color,fillcolor=green]
% \definepositionframed[z][background=color,fillcolor=blue]
-\def\remappositionframed#1#2% from to
+\unexpanded\def\remappositionframed#1#2% from to
{\copyposition{b:#1}{b:#2}%
\copyposition{e:#1}{e:#2}%
- \dosetpositionaction{b:#2}{\dopositionaction{b:#1}}}
+ \anch_positions_set_action{b:#2}{\dopositionaction{b:#1}}}
\unexpanded\def\definepositionframed
- {\dodoubleargument\dodefinepositionframed}
+ {\dodoubleargument\anch_framed_define}
-\def\dodefinepositionframed[#1][#2]%
- {\dosetpositionaction{b:#1}{\dopositionframed[#1][#2]}}
+\def\anch_framed_define[#1][#2]%
+ {\anch_positions_set_action{b:#1}{\anch_framed_handle[#1][#2]}}
+
+\unexpanded\def\anch_framed_handle
+ {\bgroup
+ \anch_framed_indeed}
\unexpanded\def\positionframed
{\bgroup
- \dodoubleempty\dopositionframed}
+ \dodoubleempty\anch_framed_indeed}
-\def\dopositionframed[#1][#2]%
+\def\anch_framed_indeed[#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
diff --git a/tex/context/base/attr-col.lua b/tex/context/base/attr-col.lua
index c592d1dc1..18182ba85 100644
--- a/tex/context/base/attr-col.lua
+++ b/tex/context/base/attr-col.lua
@@ -15,8 +15,11 @@ if not modules then modules = { } end modules ['attr-col'] = {
local type = type
local format = string.format
local concat = table.concat
+local min, max, floor = math.min, math.max, math.floor
-local attributes, nodes = attributes, nodes
+local attributes, nodes, utilities, logs, backends, storage = attributes, nodes, utilities, logs, backends, storage
+local commands, context, interfaces = commands, context, interfaces
+local tex = tex
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -31,11 +34,13 @@ local report_transparencies = logs.reporter("transparencies","support")
-- nb: attributes: color etc is much slower than normal (marks + literals) but ...
-- nb. too many "0 g"s
-local states = attributes.states
-local tasks = nodes.tasks
-local nodeinjections = backends.nodeinjections
-local registrations = backends.registrations
-local unsetvalue = attributes.unsetvalue
+local states = attributes.states
+local tasks = nodes.tasks
+local nodeinjections = backends.nodeinjections
+local registrations = backends.registrations
+local unsetvalue = attributes.unsetvalue
+
+local registerstorage = storage.register
-- We can distinguish between rules and glyphs but it's not worth the trouble. A
-- first implementation did that and while it saves a bit for glyphs and rules, it
@@ -63,7 +68,7 @@ local unsetvalue = attributes.unsetvalue
-- colors.strings[color] = "return colors." .. colorspace .. "(" .. concat({...},",") .. ")"
-- end
--
--- storage.register("attributes/colors/data", colors.strings, "attributes.colors.data") -- evaluated
+-- registerstorage("attributes/colors/data", colors.strings, "attributes.colors.data") -- evaluated
--
-- We assume that only processcolors are defined in the format.
@@ -83,9 +88,17 @@ colors.default = 1
colors.main = nil
colors.triggering = true
colors.supported = true
+colors.model = "all"
+
+local data = colors.data
+local values = colors.values
+local registered = colors.registered
-storage.register("attributes/colors/values", colors.values, "attributes.colors.values")
-storage.register("attributes/colors/registered", colors.registered, "attributes.colors.registered")
+local numbers = attributes.numbers
+local list = attributes.list
+
+registerstorage("attributes/colors/values", values, "attributes.colors.values")
+registerstorage("attributes/colors/registered", registered, "attributes.colors.registered")
local templates = {
rgb = "r:%s:%s:%s",
@@ -104,17 +117,6 @@ local models = {
cmyk = 4,
}
-colors.model = "all"
-
-local data = colors.data
-local values = colors.values
-local registered = colors.registered
-
-local numbers = attributes.numbers
-local list = attributes.list
-
-local min, max, floor = math.min, math.max, math.floor
-
local function rgbtocmyk(r,g,b) -- we could reduce
return 1-r, 1-g, 1-b, 0
end
@@ -125,9 +127,9 @@ end
local function rgbtogray(r,g,b)
if colors.weightgray then
- return .30*r+.59*g+.11*b
+ return .30*r + .59*g + .11*b
else
- return r/3+g/3+b/3
+ return r/3 + g/3 + b/3
end
end
@@ -135,6 +137,17 @@ local function cmyktogray(c,m,y,k)
return rgbtogray(cmyktorgb(c,m,y,k))
end
+-- not critical so not needed:
+--
+-- local function cmyktogray(c,m,y,k)
+-- local r, g, b = 1.0 - min(1.0,c+k), 1.0 - min(1.0,m+k), 1.0 - min(1.0,y+k)
+-- if colors.weightgray then
+-- return .30*r + .59*g + .11*b
+-- else
+-- return r/3 + g/3 + b/3
+-- end
+-- end
+
-- http://en.wikipedia.org/wiki/HSI_color_space
-- http://nl.wikipedia.org/wiki/HSV_(kleurruimte)
@@ -363,15 +376,15 @@ transparencies.triggering = true
transparencies.attribute = a_transparency
transparencies.supported = true
-storage.register("attributes/transparencies/registered", transparencies.registered, "attributes.transparencies.registered")
-storage.register("attributes/transparencies/values", transparencies.values, "attributes.transparencies.values")
+local registered = transparencies.registered -- we could use a 2 dimensional table instead
+local data = transparencies.data
+local values = transparencies.values
+local template = "%s:%s"
-local registered = transparencies.registered -- we could use a 2 dimensional table instead
-local data = transparencies.data
-local values = transparencies.values
-local template = "%s:%s"
+registerstorage("attributes/transparencies/registered", registered, "attributes.transparencies.registered")
+registerstorage("attributes/transparencies/values", values, "attributes.transparencies.values")
-local function inject_transparency (...)
+local function inject_transparency(...)
inject_transparency = nodeinjections.transparency
return inject_transparency(...)
end
diff --git a/tex/context/base/attr-eff.lua b/tex/context/base/attr-eff.lua
index 023d1c51b..60e0c08ac 100644
--- a/tex/context/base/attr-eff.lua
+++ b/tex/context/base/attr-eff.lua
@@ -8,7 +8,9 @@ if not modules then modules = { } end modules ['attr-eff'] = {
local format = string.format
-local attributes, nodes = attributes, nodes
+local commands, interfaces = commands, interfaces
+local attributes, nodes, backends, utilities = attributes, nodes, backends, utilities
+local tex = tex
local states = attributes.states
local tasks = nodes.tasks
@@ -17,6 +19,9 @@ local settexattribute = tex.setattribute
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
+local variables = interfaces.variables
+local v_normal = variables.normal
+
attributes.effects = attributes.effects or { }
local effects = attributes.effects
@@ -27,14 +32,14 @@ effects.values = effects.values or { }
effects.registered = effects.registered or { }
effects.attribute = a_effect
-storage.register("attributes/effects/registered", effects.registered, "attributes.effects.registered")
-storage.register("attributes/effects/values", effects.values, "attributes.effects.values")
+local data = effects.data
+local registered = effects.registered
+local values = effects.values
-local template = "%s:%s:%s"
+local template = "%s:%s:%s"
-local data = effects.data
-local registered = effects.registered
-local values = effects.values
+storage.register("attributes/effects/registered", registered, "attributes.effects.registered")
+storage.register("attributes/effects/values", values, "attributes.effects.values")
-- valid effects: normal inner outer both hidden (stretch,rulethickness,effect)
@@ -66,12 +71,22 @@ effects.handler = nodes.installattributehandler {
processor = states.process,
}
-local function register(effect,stretch,rulethickness)
- local stamp = format(template,effect,stretch,rulethickness)
+local function register(specification)
+ local alternative, stretch, rulethickness
+ if specification then
+ alternative = specification.alternative or v_normal
+ stretch = specification.stretch or 0
+ rulethickness = specification.rulethickness or 0
+ else
+ alternative = v_normal
+ stretch = 0
+ rulethickness = 0
+ end
+ local stamp = format(template,alternative,stretch,rulethickness)
local n = registered[stamp]
if not n then
n = #values + 1
- values[n] = { effect, stretch, rulethickness }
+ values[n] = { alternative, stretch, rulethickness }
registered[stamp] = n
end
return n
@@ -88,10 +103,10 @@ effects.enable = enable
local enabled = false
-function commands.triggereffect(effect,stretch,rulethickness)
+function commands.triggereffect(specification)
if not enabled then
enable()
enabled = true
end
- settexattribute(a_effect,register(effect,stretch,rulethickness))
+ settexattribute(a_effect,register(specification))
end
diff --git a/tex/context/base/attr-eff.mkiv b/tex/context/base/attr-eff.mkiv
index c5c94537c..43f575a7a 100644
--- a/tex/context/base/attr-eff.mkiv
+++ b/tex/context/base/attr-eff.mkiv
@@ -17,38 +17,39 @@
\unprotect
-\gdef\dotriggereffect#1#2#3%
- {\ctxcommand{triggereffect('#1',#2,\number\dimexpr#3\relax)}}
+\installcorenamespace{effect}
-\unexpanded\def\setupeffect
- {\dodoubleargument\dosetupeffect}
+\installcommandhandler \??effect {effect} \??effect
-\def\dosetupeffect[#1][#2]%
- {\getparameters[\??et#1][#2]}
+\setupeffect
+ [\c!method=\v!none,
+ \c!stretch=\zerocount,
+ \c!rulethickness=\zeropoint,
+ \c!alternative=\v!normal]
-\unexpanded\def\defineeffect
- {\dodoubleargument\dodefineeffect}
-
-\def\dodefineeffect[#1][#2]%
- {\getparameters[\??et#1][\c!method=\v!none,\c!stretch=0,\c!rulethickness=\zeropoint,\c!alternative=\v!normal,#2]%
- \doif{\getvalue{\??et#1\c!method}}\v!command
- {\setugvalue{\e!start#1}{\starteffect[#1]}%
- \setugvalue{\e!stop #1}{\stopeffect}}}
-
-% yes or no grouped
+\appendtoks
+ \edef\p_method{\effectparameter\c!method}%
+ \ifx\p_method\v!method
+ \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}%
+ \setuxvalue{\e!stop \currenteffect}{\stopeffect}%
+ \fi
+\to \everydefineeffect
\unexpanded\def\starteffect[#1]%
- {\dotriggereffect
- {\csname\??et#1\c!alternative \endcsname}%
- {\csname\??et#1\c!stretch \endcsname}%
- {\csname\??et#1\c!rulethickness\endcsname}}
+ {\ctxcommand{triggereffect{
+ alternative = "\namedeffectparameter{#1}\c!alternative",
+ stretch = \number\namedeffectparameter{#1}\c!stretch,
+ rulethickness = \number\dimexpr\namedeffectparameter{#1}\c!rulethickness\relax
+ }}}
\unexpanded\def\stopeffect % can be special
- {\dotriggereffect\v!normal0\zeropoint}
+ {\ctxcommand{triggereffect()}} % v!normal 0 0
\unexpanded\def\effect[#1]%
{\groupedcommand{\starteffect[#1]}{\stopeffect}}
+% yes or no grouped
+
\defineeffect [\v!inner] [\c!alternative=\v!inner,\c!rulethickness=.25pt]
\defineeffect [\v!outer] [\c!alternative=\v!outer,\c!rulethickness=.25pt]
\defineeffect [\v!both] [\c!alternative=\v!both, \c!rulethickness=.25pt]
diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua
index f3714fcb4..5a3bafce3 100644
--- a/tex/context/base/attr-ini.lua
+++ b/tex/context/base/attr-ini.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['attr-ini'] = {
license = "see context related readme files"
}
+local commands, context, nodes, storage = commands, context, nodes, storage
+
local next, type = next, type
--[[ldx--
@@ -13,11 +15,10 @@ local next, type = next, type
symbolic names later on.</p>
--ldx]]--
-attributes = attributes or { }
-
-local attributes, nodes = attributes, nodes
+attributes = attributes or { }
+local attributes = attributes
--- todo: local and then gobals ... first loaded anyway
+local sharedstorage = storage.shared
attributes.names = attributes.names or { }
attributes.numbers = attributes.numbers or { }
@@ -26,15 +27,14 @@ attributes.states = attributes.states or { }
attributes.handlers = attributes.handlers or { }
attributes.unsetvalue = -0x7FFFFFFF
-local names, numbers, list = attributes.names, attributes.numbers, attributes.list
+local names = attributes.names
+local numbers = attributes.numbers
+local list = attributes.list
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] = number
@@ -44,12 +44,18 @@ function attributes.define(name,number) -- at the tex end
end
--[[ldx--
+<p>We reserve this one as we really want it to be always set (faster).</p>
+--ldx]]--
+
+names[0], numbers["fontdynamic"] = "fontdynamic", 0
+
+--[[ldx--
<p>We can use the attributes in the range 127-255 (outside user space). These
are only used when no attribute is set at the \TEX\ end which normally
happens in <l n='context'/>.</p>
--ldx]]--
-storage.shared.attributes_last_private = storage.shared.attributes_last_private or 127
+sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 127
-- to be considered (so that we can use an array access):
--
@@ -57,10 +63,10 @@ storage.shared.attributes_last_private = storage.shared.attributes_last_private
--
-- setmetatable(private, {
-- __index = function(t,name)
--- local number = storage.shared.attributes_last_private or 127
+-- local number = sharedstorage.attributes_last_private
-- if number < 1023 then -- tex.count.minallocatedattribute - 1
-- number = number + 1
--- storage.shared.attributes_last_private = number
+-- sharedstorage.attributes_last_private = number
-- end
-- numbers[name], names[number], list[number] = number, name, { }
-- private[name] = number
@@ -74,12 +80,12 @@ storage.shared.attributes_last_private = storage.shared.attributes_last_private
function attributes.private(name) -- at the lua end (hidden from user)
local number = numbers[name]
if not number then
- local last = storage.shared.attributes_last_private or 127
+ local last = sharedstorage.attributes_last_private
if last < 1023 then -- tex.count.minallocatedattribute - 1
last = last + 1
- storage.shared.attributes_last_private = last
+ sharedstorage.attributes_last_private = last
else
- report_attribute("no more room for private attributes") -- fatal
+ report_attribute("no more room for private attributes")
os.exit()
end
number = last
@@ -88,7 +94,7 @@ function attributes.private(name) -- at the lua end (hidden from user)
return number
end
--- new (actually a tracer)
+-- tracers
local report_attribute = logs.reporter("attributes")
diff --git a/tex/context/base/attr-ini.mkiv b/tex/context/base/attr-ini.mkiv
index a1550b4be..8a41dd427 100644
--- a/tex/context/base/attr-ini.mkiv
+++ b/tex/context/base/attr-ini.mkiv
@@ -14,8 +14,8 @@
\writestatus{loading}{ConTeXt Attribute Macros / Initialization}
%D Although it's still somewhat experimental, here we introduce code
-%D related to attributes. Housekeeping will move completely to Lua
-%D and \newattribute will go away.
+%D related to attributes. Housekeeping will move completely to \LUA\
+%D and \type {\newattribute} will go away.
\unprotect
@@ -27,14 +27,16 @@
\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}
+ \expandafter\xdef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname{\number\attribute#1}}
\unexpanded\def\popattribute#1%
- {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname
+ {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\relax
\global\advance\csname\??attributestack\string#1\endcsname\minusone}
\unexpanded\def\installattributestack#1%
- {\expandafter\newcount\csname\??attributestack\string#1\endcsname}
+ {\ifcsname\??attributestack\string#1\endcsname \else
+ \expandafter\newcount\csname\??attributestack\string#1\endcsname
+ \fi}
\newtoks \attributesresetlist
diff --git a/tex/context/base/attr-lay.lua b/tex/context/base/attr-lay.lua
index bcdc541f7..5e5e81ff1 100644
--- a/tex/context/base/attr-lay.lua
+++ b/tex/context/base/attr-lay.lua
@@ -10,9 +10,15 @@ if not modules then modules = { } end modules ['attr-lay'] = {
-- but when we need it stacked layers might show up too; the next function based
-- approach can be replaced by static (metatable driven) resolvers
+-- maybe use backends.registrations here too
+
local type = type
local format = string.format
-local insert, remove = table.insert, table.remove
+local insert, remove, concat = table.insert, table.remove, table.concat
+
+local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends
+local commands, context, interfaces = commands, context, interfaces
+local tex = tex
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -26,8 +32,6 @@ local report_viewerlayers = logs.reporter("viewerlayers")
-- nb. too many "0 g"s
-- nb: more local tables
-local attributes, nodes = attributes, nodes
-
attributes.viewerlayers = attributes.viewerlayers or { }
local viewerlayers = attributes.viewerlayers
@@ -57,22 +61,42 @@ local texgetattribute = tex.getattribute
local texsettokenlist = tex.settoks
local unsetvalue = attributes.unsetvalue
-storage.register("attributes/viewerlayers/registered", viewerlayers.registered, "attributes.viewerlayers.registered")
-storage.register("attributes/viewerlayers/values", viewerlayers.values, "attributes.viewerlayers.values")
-storage.register("attributes/viewerlayers/scopes", viewerlayers.scopes, "attributes.viewerlayers.scopes")
+local nodepool = nodes.pool
+
+local data = viewerlayers.data
+local values = viewerlayers.values
+local listwise = viewerlayers.listwise
+local registered = viewerlayers.registered
+local scopes = viewerlayers.scopes
+
+local template = "%s"
-local data = viewerlayers.data
-local values = viewerlayers.values
-local listwise = viewerlayers.listwise
-local registered = viewerlayers.registered
-local scopes = viewerlayers.scopes
-local template = "%s"
+storage.register("attributes/viewerlayers/registered", registered, "attributes.viewerlayers.registered")
+storage.register("attributes/viewerlayers/values", values, "attributes.viewerlayers.values")
+storage.register("attributes/viewerlayers/scopes", scopes, "attributes.viewerlayers.scopes")
+
+local layerstacker = utilities.stacker.new("layers") -- experiment
+
+layerstacker.mode = "stack"
+layerstacker.unset = attributes.unsetvalue
+
+viewerlayers.resolve_begin = layerstacker.resolve_begin
+viewerlayers.resolve_step = layerstacker.resolve_step
+viewerlayers.resolve_end = layerstacker.resolve_end
+
+function commands.cleanuplayers()
+ layerstacker.clean()
+ -- todo
+end
-- stacked
+local function startlayer(...) startlayer = nodeinjections.startlayer return startlayer(...) end
+local function stoplayer (...) stoplayer = nodeinjections.stoplayer return stoplayer (...) end
+
local function extender(viewerlayers,key)
if viewerlayers.supported and key == "none" then
- local d = nodeinjections.stoplayer()
+ local d = stoplayer()
viewerlayers.none = d
return d
end
@@ -82,7 +106,7 @@ local function reviver(data,n)
if viewerlayers.supported then
local v = values[n]
if v then
- local d = nodeinjections.startlayer(v)
+ local d = startlayer(v)
data[n] = d
return d
else
@@ -91,8 +115,14 @@ local function reviver(data,n)
end
end
-setmetatableindex(viewerlayers, extender)
-setmetatableindex(viewerlayers.data, reviver)
+setmetatableindex(viewerlayers,extender)
+setmetatableindex(viewerlayers.data,reviver)
+
+-- !!!! TEST CODE !!!!
+
+layerstacker.start = function(...) local f = nodeinjections.startstackedlayer layerstacker.start = f return f(...) end
+layerstacker.stop = function(...) local f = nodeinjections.stopstackedlayer layerstacker.stop = f return f(...) end
+layerstacker.change = function(...) local f = nodeinjections.changestackedlayer layerstacker.change = f return f(...) end
local function initializer(...)
return states.initialize(...)
@@ -103,7 +133,8 @@ attributes.viewerlayers.handler = nodes.installattributehandler {
namespace = viewerlayers,
initializer = initializer,
finalizer = states.finalize,
- processor = states.stacked,
+ -- processor = states.stacked,
+ processor = states.stacker,
}
local stack, enabled, global = { }, false, false
@@ -149,12 +180,16 @@ function viewerlayers.setfeatures(hasorder)
viewerlayers.hasorder = hasorder
end
+local usestacker = true -- new, experimental
+
function viewerlayers.start(name)
--- if not enabled then
--- viewerlayers.enable(true)
--- end
- insert(stack,texgetattribute(a_viewerlayer))
- local a = register(name) or unsetvalue
+ local a
+ if usestacker then
+ a = layerstacker.push(register(name) or unsetvalue)
+ else
+ insert(stack,texgetattribute(a_viewerlayer))
+ a = register(name) or unsetvalue
+ end
if global or scopes[name] == v_global then
scopes[a] = v_global -- messy but we don't know the attributes yet
texsetattribute("global",a_viewerlayer,a)
@@ -165,14 +200,21 @@ function viewerlayers.start(name)
end
function viewerlayers.stop()
- local a = remove(stack)
- if a >= 0 then
+ local a
+ if usestacker then
+ a = layerstacker.pop()
+ else
+ a = remove(stack)
+ end
+ if not a then
+ -- error
+ elseif a >= 0 then
if global or scopes[a] == v_global then
texsetattribute("global",a_viewerlayer,a)
else
texsetattribute(a_viewerlayer,a)
end
- texsettokenlist("currentviewerlayertoks",values[a])
+ texsettokenlist("currentviewerlayertoks",values[a] or "")
else
if global or scopes[a] == v_global then
texsetattribute("global",a_viewerlayer,unsetvalue)
@@ -197,9 +239,9 @@ function viewerlayers.define(settings)
end
end
-commands.defineviewerlayer = viewerlayers.define
-commands.startviewerlayer = viewerlayers.start
-commands.stopviewerlayer = viewerlayers.stop
+commands.defineviewerlayer = viewerlayers.define
+commands.startviewerlayer = viewerlayers.start
+commands.stopviewerlayer = viewerlayers.stop
function commands.definedviewerlayer(settings)
viewerlayers.define(settings)
diff --git a/tex/context/base/attr-lay.mkiv b/tex/context/base/attr-lay.mkiv
index 67cd204e2..9c9c3318e 100644
--- a/tex/context/base/attr-lay.mkiv
+++ b/tex/context/base/attr-lay.mkiv
@@ -13,51 +13,51 @@
\writestatus{loading}{ConTeXt Attribute Macros / Viewerlayers}
+%D Currently there is a limitation in mixed inline usage. This has to do with the fact
+%D that we have a stacked model but cannot determine where to revert to (as we can
+%D have AABBCCAA ranges). Maybe I'll solve that one day. It only affects nested inline
+%D layers and these make not much sense anyway. We'd have to store the complete nesting
+%D stack in the attribute in order to be able to cross pages and that demands a new
+%D mechanism.
+
\unprotect
\registerctxluafile{attr-lay}{1.001}
% needs to work over stopitemize grouping etc
-% \def\registerviewerlayer#1#2% global !
-% {\setxvalue{\??ql:#1}{\global\attribute\viewerlayerattribute\ctxlua{tex.write(attributes.viewerlayers.register('#2'))} }}
-%
-% \setevalue{\??ql:}{\global\attribute\viewerlayerattribute\attributeunsetvalue}
+\installcorenamespace{viewerlayer}
+
+\installcommandhandler \??viewerlayer {viewerlayer} \??viewerlayer
-\getparameters
- [\??lr]
+\setupviewerlayer
[\c!state=\v!start,
\c!title=,
\c!printable=\v!yes,
\c!scope=\v!local, % maybe global but needs checking with layout
\c!method=\v!none]
-\def\defineviewerlayer
- {\dodoubleargument\dodefineviewerlayer}
-
-\def\dodefineviewerlayer[#1][#2]% document wide properties
- {\begingroup
- \getparameters[\??lr][#2]%
- \ctxcommand{defineviewerlayer{
- tag = "#1",
- title = "\@@lrtitle",
- visible = "\@@lrstate",
- editable = "\v!yes",
- printable = "\@@lrprintable",
- scope = "\@@lrscope"
- }}%
- \doif\@@lrmethod\v!command
- {\setugvalue{\e!start#1}{\startviewerlayer[#1]}%
- \setugvalue{\e!stop #1}{\stopviewerlayer }}%
- \endgroup}
-
-\unexpanded\def\startviewerlayer[#1]{\ctxcommand{startviewerlayer("#1")}} % not grouped
-\unexpanded\def\stopviewerlayer {\ctxcommand{stopviewerlayer()}} % not grouped
+\appendtoks
+ \ctxcommand{defineviewerlayer{
+ tag = "\currentviewerlayer",
+ title = "\viewerlayerparameter\c!title",
+ visible = "\viewerlayerparameter\c!state",
+ editable = "\v!yes",
+ printable = "\viewerlayerparameter\c!printable",
+ scope = "\viewerlayerparameter\c!scope"
+ }}%
+ \doif{\viewerlayerparameter\c!method}\v!command
+ {\setuxvalue{\e!start#1}{\startviewerlayer[\currentviewerlayer]}%
+ \setuxvalue{\e!stop #1}{\stopviewerlayer}}%
+\to \everydefineviewerlayer
+
+\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
-\let\currentviewerlayer\empty \newtoks\currentviewerlayertoks % soon we can set macros at the lua end
+\newtoks\currentviewerlayertoks % soon we can set macros at the lua end
\def\currentviewerlayer{\the\currentviewerlayertoks}
@@ -67,7 +67,9 @@
% layout components are implemented rather directly (speed)
-\def\doinitializelayoutcomponent#1%
+\installcorenamespace{layoutcomponentattribute}
+
+\def\attr_layoutcomponent_initialize#1%
{\edef\layoutcomponentboxattribute{\ctxcommand{definedviewerlayer{%
tag = "#1",
title = utilities.strings.nice("#1"), % only here as in steps we have step:<number>
@@ -76,24 +78,28 @@
printable = "\v!yes"
}}}%
\edef\layoutcomponentboxattribute{attr \viewerlayerattribute \layoutcomponentboxattribute\relax}%
- \expandafter\glet\csname\??lr:a:#1\endcsname\layoutcomponentboxattribute}
+ \expandafter\glet\csname\??layoutcomponentattribute#1\endcsname\layoutcomponentboxattribute}
-\def\dosetlayoutcomponentattribute#1% make this faster
- {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??lr:a:#1\endcsname
+\def\attr_layoutcomponent_set#1% make this faster
+ {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??layoutcomponentattribute#1\endcsname
\ifx\layoutcomponentboxattribute\relax
- \doinitializelayoutcomponent{#1}% get rid of { }
+ \attr_layoutcomponent_initialize{#1}% get rid of { }
\fi}
-\def\doresetlayoutcomponentattribute
+\def\attr_layoutcomponent_reset
{\let\layoutcomponentboxattribute\empty}
\let\setlayoutcomponentattribute \gobbleoneargument
\let\resetlayoutcomponentattribute\relax
\let\layoutcomponentboxattribute \empty
-\def\showlayoutcomponents
- {\ctxlua{attributes.viewerlayers.enable()}% will go
- \let\setlayoutcomponentattribute \dosetlayoutcomponentattribute
- \let\resetlayoutcomponentattribute\doresetlayoutcomponentattribute}
+\unexpanded\def\showlayoutcomponents
+ {%\ctxlua{attributes.viewerlayers.enable()}% automatic
+ \let\setlayoutcomponentattribute \attr_layoutcomponent_set
+ \let\resetlayoutcomponentattribute\attr_layoutcomponent_reset}
+
+\appendtoks
+ \ctxcommand{cleanuplayers()}%
+\to \everyshipout
\protect \endinput
diff --git a/tex/context/base/attr-neg.lua b/tex/context/base/attr-neg.lua
index 4d89cb49b..c32cec956 100644
--- a/tex/context/base/attr-neg.lua
+++ b/tex/context/base/attr-neg.lua
@@ -11,8 +11,9 @@ if not modules then modules = { } end modules ['attr-neg'] = {
local format = string.format
-
-local attributes, nodes = attributes, nodes
+local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends
+local commands, context, interfaces = commands, context, interfaces
+local tex = tex
local states = attributes.states
local tasks = nodes.tasks
diff --git a/tex/context/base/attr-neg.mkiv b/tex/context/base/attr-neg.mkiv
index 0fc5070f1..102b220ba 100644
--- a/tex/context/base/attr-neg.mkiv
+++ b/tex/context/base/attr-neg.mkiv
@@ -19,12 +19,12 @@
% positive and negative are preregistered
-\def\dotriggernegative#1{\ctxcommand{triggernegative('#1')}}
+\unexpanded\def\startnegative{\attr_trigger_negative\v!negative}
+\unexpanded\def\stopnegative {\attr_trigger_negative\v!positive}
-\unexpanded\def\startnegative{\dotriggernegative\v!negative}
-\unexpanded\def\stopnegative {\dotriggernegative\v!positive}
+\unexpanded\def\startpositive{\attr_trigger_negative\v!positive}
+\unexpanded\def\stoppositive {\attr_trigger_negative\v!negative}
-\unexpanded\def\startpositive{\dotriggernegative\v!positive}
-\unexpanded\def\stoppositive {\dotriggernegative\v!negative}
+\def\attr_trigger_negative#1{\ctxcommand{triggernegative('#1')}}
\protect \endinput
diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua
index 3ce40a6c5..46ce4f96c 100644
--- a/tex/context/base/back-exp.lua
+++ b/tex/context/base/back-exp.lua
@@ -20,8 +20,9 @@ if not modules then modules = { } end modules ['back-exp'] = {
local next, type = next, type
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 validstring = string.valid
local lpegmatch = lpeg.match
-local utfchar, utfbyte, utfsub, utfgsub = utf.char, utf.byte, utf.sub, utf.gsub
+local utfchar, utfbyte = utf.char, utf.byte
local insert, remove = table.insert, table.remove
local topoints = number.topoints
local utfvalues = string.utfvalues
@@ -154,6 +155,8 @@ local somespace = { [0x20] = true, [" "] = true } -- for testing
local entities = { ["&"] = "&amp;", [">"] = "&gt;", ["<"] = "&lt;" }
local attribentities = { ["&"] = "&amp;", [">"] = "&gt;", ["<"] = "&lt;", ['"'] = "quot;" }
+local entityremapper = utf.remapper(entities)
+
local alignmapping = {
flushright = "right",
middle = "center",
@@ -300,7 +303,7 @@ local usedstyles = { }
local documenttemplate = [[
document {
- font-size : %s !important ;
+ font-size : %s !important ;
max-width : %s !important ;
text-align : %s !important ;
hyphens : %s !important ;
@@ -382,7 +385,7 @@ local function allusedimages(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
+ if file.suffix(name) == "pdf" then
-- temp hack .. we will have a remapper
name = file.replacesuffix(name,"svg")
end
@@ -397,7 +400,7 @@ local function uniqueusedimages()
for element, details in next, usedimages do
for detail, data in next, details do
local name = data.name
- if file.extname(name) == "pdf" then
+ if file.suffix(name) == "pdf" then
unique[file.replacesuffix(name,"svg")] = name
else
unique[name] = name
@@ -1351,7 +1354,7 @@ local function begintag(result,element,nature,depth,di,skip)
end
result[#result+1] = format("%s<metadata>\n",spaces[depth])
for k, v in table.sortedpairs(metadata) do
- v = utfgsub(v,".",entities)
+ v = entityremapper(v)
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])
@@ -1409,7 +1412,7 @@ local function flushtree(result,data,nature,depth)
-- whatever
elseif di.content then
-- already has breaks
- local content = utfgsub(di.content,".",entities)
+ local content = entityremapper(di.content)
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
@@ -2362,12 +2365,21 @@ local function stopexport(v)
report_export("saving xhtml variant in '%s",xhtmlfile)
local xmltree = cleanxhtmltree(xml.convert(results))
xml.save(xmltree,xhtmlfile)
+ -- looking at identity is somewhat redundant as we also inherit from interaction
+ -- at the tex end
+ local identity = interactions.general.getidentity()
local specification = {
name = file.removesuffix(v),
identifier = os.uuid(),
images = uniqueusedimages(),
root = xhtmlfile,
files = files,
+ language = languagenames[tex.count.mainlanguagenumber],
+ title = validstring(finetuning.title) or validstring(identity.title),
+ subtitle = validstring(finetuning.subtitle) or validstring(identity.subtitle),
+ author = validstring(finetuning.author) or validstring(identity.author),
+ firstpage = validstring(finetuning.firstpage),
+ lastpage = validstring(finetuning.lastpage),
}
report_export("saving specification in '%s' (mtxrun --script epub --make %s)",specificationfilename,specificationfilename)
io.savedata(specificationfilename,table.serialize(specification,true))
diff --git a/tex/context/base/back-exp.mkiv b/tex/context/base/back-exp.mkiv
index 871d08b19..9e65633d4 100644
--- a/tex/context/base/back-exp.mkiv
+++ b/tex/context/base/back-exp.mkiv
@@ -132,6 +132,11 @@
[\c!align=\number\raggedstatus,
\c!bodyfont=\bodyfontsize,
\c!width=\textwidth,
+ \c!title={\directinteractionparameter\c!title},
+ \c!subtitle={\directinteractionparameter\c!subtitle},
+ \c!author={\directinteractionparameter\c!author},
+ % \c!firstpage=, % imagename
+ % \c!lastpage=, % imagename
\c!hyphen=\v!no]
\def\dosynchronizeexport
@@ -141,13 +146,22 @@
bodyfont = \number\dimexpr\exportparameter\c!bodyfont,
width = \number\dimexpr\exportparameter\c!width,
hyphen = "\exportparameter\c!hyphen",
+ title = \!!bs\exportparameter\c!title\!!es,
+ subtitle = \!!bs\exportparameter\c!subtitle\!!es,
+ author = \!!bs\exportparameter\c!author\!!es,
+ firstpage = "\exportparameter\c!firstpage",
+ lastpage = "\exportparameter\c!lastpage",
}}}
\appendtoks
- \doifsomething{\backendparameter\c!export}{\dosynchronizeexport}%
+ \doifsomething{\backendparameter\c!export}\dosynchronizeexport
\to \everystarttext
\appendtoks
+ \doifsomething{\backendparameter\c!export}\dosynchronizeexport % in case it is done inside \starttext
+\to \everysetupdocument
+
+\appendtoks
\doifsomething{\backendparameter\c!xhtml}
{\enabledirectives[backend.export.xhtml=\backendparameter\c!xhtml]}%
\doifsomething{\backendparameter\c!css}
@@ -155,11 +169,11 @@
\to \everysetupbackend
\appendtoks
- \doifsomething{\backendparameter\c!export}
- {\setuptagging
- [\c!state=\v!start]%
- \enabledirectives
- [backend.export=\backendparameter\c!export]}%
+ \doifelsenothing{\backendparameter\c!export}
+ {\resetsystemmode\v!export}
+ {\setuptagging[\c!state=\v!start]%
+ \enabledirectives[backend.export=\backendparameter\c!export]%
+ \setsystemmode\v!export}%
\to \everysetupbackend
\protect \endinput
diff --git a/tex/context/base/back-ini.lua b/tex/context/base/back-ini.lua
index 0c02e201a..f76b85438 100644
--- a/tex/context/base/back-ini.lua
+++ b/tex/context/base/back-ini.lua
@@ -93,9 +93,9 @@ tables.vfspecials = allocate {
stopslant = comment,
}
--- -- experimental code --
+-- experimental code --
-function commands.pdfrotation(a)
+function commands.pdfrotation(a) -- somewhat weird here
local s, c = sind(a), cosd(a)
context("%s %s %s %s",c,s,-s,c)
end
diff --git a/tex/context/base/back-ini.mkiv b/tex/context/base/back-ini.mkiv
index 8ece8f6e1..fc8759c14 100644
--- a/tex/context/base/back-ini.mkiv
+++ b/tex/context/base/back-ini.mkiv
@@ -61,13 +61,13 @@
\let \dotransformnextbox\gobblesixarguments % and pass last box
%D \macros
-%D {doovalbox}
+%D {back_ovalbox}
%D
%D When we look at the implementation, this is a complicated
%D one. There are seven arguments.
%D
%D \starttyping
-%D \doovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant}
+%D \back_ovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant}
%D \stoptyping
%D
%D This command has to return a \type{\vbox} which can be used
@@ -75,7 +75,7 @@
%D degrees, the stroke and fill are~\type{1} (true) of~\type{0}
%D (false).
-\let \doovalbox \gobbleeightarguments
+\let\back_ovalbox \gobbleeightarguments
%D \macros
%D {dostartclipping,dostopclipping}
diff --git a/tex/context/base/back-pdf.mkiv b/tex/context/base/back-pdf.mkiv
index 9e441e224..7e910f07f 100644
--- a/tex/context/base/back-pdf.mkiv
+++ b/tex/context/base/back-pdf.mkiv
@@ -68,16 +68,17 @@
{\ctxcommand{setxmpfile("\backendparameter{xmpfile}")}}%
\to \everysetupbackend
+% \doifsomething{\backendparameter\c!format} .. at the lua end
+
\appendtoks
- \doifsomething{\backendparameter\c!format}
- {\ctxcommand{setformat {
+ \ctxcommand{setformat {
format = "\backendparameter\c!format",
level = "\backendparameter\c!level",
option = "\backendparameter\c!option",
profile = "\backendparameter\c!profile",
intent = "\backendparameter\c!intent",
file = "\backendparameter\c!file",
- }}}%
+ }}%
\to \everysetupbackend
%D For the moment we keep these.
@@ -220,12 +221,12 @@
\newbox\objectbox
-\def\dostartobject#1#2#3#4#5%
+\unexpanded\def\dostartobject#1#2#3#4#5% needs to be \unexpanded
{\bgroup
\setbox\objectbox\vbox\bgroup
\def\back_object_stop{\egroup\back_object_register{#1}{#2}}}
-\def\dostopobject
+\unexpanded\def\dostopobject % needs to be \unexpanded
{\back_object_stop
\egroup}
@@ -237,9 +238,6 @@
\immediate\pdfxform resources {\pdfbackendcurrentresources}\objectbox
\dosetobjectreference{#1}{#2}{\the\pdflastxform}}
-\def\doresetobjects
- {}
-
\let\m_back_object_reference\empty
\def\doinsertobject#1#2%
@@ -263,7 +261,7 @@
% for the moment here
%D \macros
-%D {doovalbox}
+%D {back_ovalbox}
%D
%D Drawing frames with round corners is inherited from the
%D main module.
@@ -276,7 +274,7 @@
% \def\back_oval_calculate#1#2#3%
% {\PointsToBigPoints{\dimexpr#2+#3\relax}#1}
-\unexpanded\def\doovalbox#1#2#3#4#5#6#7#8%
+\unexpanded\def\back_ovalbox#1#2#3#4#5#6#7#8%
{\forcecolorhack
\bgroup
% \scratchdimen#4%
@@ -306,16 +304,16 @@
\PointsToBigPoints{\dimexpr #2-\scratchdimen}\yymax
\PointsToBigPoints{\dimexpr-#3+\scratchdimen}\yymin
%
- \edef\dostroke{#6}%
- \edef\dofill{#7}%
- \edef\mode{\number#8 \space}%
+ \edef\dostroke{\number#6}%
+ \edef\dofill{\number#7}%
+ \edef\mode{\number#8}%
% no \ifcase, else \relax in pdfcode
\setbox\scratchbox\hbox
{\ifnum\dostroke\dofill>\zerocount
\pdfliteral
{q
\stroke\space w
- \ifcase\mode
+ \ifcase\mode\space
\xxmin\space \ymin \space m
\xxmax\space \ymin \space l
\xmax \space \ymin \space \xmax \space \yymin\space y
@@ -495,7 +493,7 @@
\xmin \space \ymin \space \xmin \space \yymin\space y
\or % 28
\fi
- \ifnum\mode>8
+ \ifnum\mode>8\space
S
\else
\ifnum\dostroke=\plusone S \fi
diff --git a/tex/context/base/back-swf.mkiv b/tex/context/base/back-swf.mkiv
index 1d225b550..09745e0f9 100644
--- a/tex/context/base/back-swf.mkiv
+++ b/tex/context/base/back-swf.mkiv
@@ -11,12 +11,12 @@
%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 This is only a placeholder that demonstrates the usage of swf resources.
+%D There is no need to include this file into the format. The module was
+%D tested by Luigi and Willi and based on their suggestions the functionality
+%D was improved.
%D
+%D \starttyping
%D \enabletrackers[graphics.locating]
%D \enabletrackers[backend.swf]
%D
@@ -41,8 +41,6 @@
%D \stopTEXpage
%D \stoptyping
-\stoptext
-
\endinput
\starttext
@@ -72,8 +70,6 @@
},
\stopluaparameterset
-\starttext
-
% preview=swf:myset:display:1
% controls=swf:myset:controls:1
% resources=swf:myset:resources:1
diff --git a/tex/context/base/back-u3d.mkiv b/tex/context/base/back-u3d.mkiv
index dfe8a90c2..89d26ee41 100644
--- a/tex/context/base/back-u3d.mkiv
+++ b/tex/context/base/back-u3d.mkiv
@@ -11,10 +11,9 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% This is only a placeholder that demonstrates the usage of u3d
-% resources. The user interface is rather messy an might be
-% improved. The files and setup is derived from an example by
-% Michael Vidiassov.
+%D This is only a placeholder that demonstrates the usage of u3d resources. The
+%D user interface is rather messy an might be improved. The files and setup is
+%D derived from an example by Michael Vidiassov.
\endinput
diff --git a/tex/context/base/bibl-bib.mkiv b/tex/context/base/bibl-bib.mkiv
index 56007d21c..7ca6799cf 100644
--- a/tex/context/base/bibl-bib.mkiv
+++ b/tex/context/base/bibl-bib.mkiv
@@ -626,7 +626,7 @@
\doifelse{\bibtexpublicationsparameter\c!method}\v!local
{\ctxlua{bibtex.hacks.reset(1)}}% function can take method
{\ctxlua{bibtex.hacks.reset(2)}}%
- \doplacestructurelist
+ \strc_lists_place_current
{\currentbibtexsession}
{\currentbibtexcriterium}
{\namedlistparameter\currentbibtexsession\c!number}%
diff --git a/tex/context/base/bibl-tra.lua b/tex/context/base/bibl-tra.lua
index 6341898ee..ca6403c44 100644
--- a/tex/context/base/bibl-tra.lua
+++ b/tex/context/base/bibl-tra.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['bibl-bib'] = {
+if not modules then modules = { } end modules ['bibl-tra'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -115,7 +115,7 @@ function hacks.registerplaced(str)
end
function hacks.doifalreadyplaced(str)
- commands.testcase(used[str])
+ commands.doifelse(used[str])
end
-- we ask for <n>:tag but when we can't find it we go back
diff --git a/tex/context/base/bibl-tra.mkiv b/tex/context/base/bibl-tra.mkiv
index 3531703ad..08d8eb6fe 100644
--- a/tex/context/base/bibl-tra.mkiv
+++ b/tex/context/base/bibl-tra.mkiv
@@ -755,7 +755,7 @@
\ctxlua{bibtex.hacks.filterall()}}
{\doif{\listparameter\c!criterium}\v!cite
{\setuplist[pubs][\c!criterium=\v!here]}%
- \doplacestructurelist
+ \strc_lists_place_current
{pubs}%
{\listparameter\c!criterium}%
{\listparameter\c!number}%
@@ -1244,7 +1244,7 @@
%D \type{\ixbibauthoryearref} stores the data in the macros
%D \type{\currentbibauthor} and \type{\currentbibyear}.
-\def\ifbibinteractionelse
+\def\doifbibinteractionelse
{\iflocation
\edef\test{\bibalternative\c!interaction}%
\ifx\test\v!stop
@@ -1256,20 +1256,11 @@
\@EA\secondoftwoarguments
\fi}
-\def\ifbibinteractionelse
- {\iflocation
- \doifelse{\bibalternative\c!interaction}\v!stop
- {\@EA\secondoftwoarguments}
- {\@EA\firstoftwoarguments}%
- \else
- \@EA\secondoftwoarguments
- \fi}
-
\def\bibmaybeinteractive#1#2%
{\ifbibcitecompress
#2%
\else
- \ifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}%
+ \doifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}%
\fi}
\def\bibauthoryearref[#1]%
@@ -1360,7 +1351,7 @@
\gotobiblink{#1}[#1]}
\def\bibgotoDOI#1#2%
- {\ifbibinteractionelse
+ {\doifbibinteractionelse
{\useURL[bibfooDoi#1][#2]%
\useURL[bibfoo#1][http://dx.doi.org/#2]%
\goto{\url[bibfooDoi#1]}[url(bibfoo#1)]}
@@ -1383,7 +1374,7 @@
\bibalternative\v!right}
\def\bibgotoURL#1#2%
- {\ifbibinteractionelse
+ {\doifbibinteractionelse
{\useURL[bibfoo#1][#2]\goto{\url[bibfoo#1]}[url(bibfoo#1)]}
{\hyphenatedurl{#2}}}
@@ -1411,7 +1402,7 @@
\def\dobibpageref#1%
{\bibinsertrefsep
- \ifbibinteractionelse
+ \doifbibinteractionelse
{\atbiblink[#1]}
{{\referencingfalse\at[#1]}}}
@@ -1484,8 +1475,6 @@
%D And some defaults are loaded from bibl-apa:
-\def\c!monthconversion{monthconversion} % todo
-
\setuppublications
[\c!monthconversion=,
\c!alternative=apa,
@@ -1502,4 +1491,6 @@
% \appendtoks \preloadbiblist \to \everysetuppublications
% \appendtoks \preloadbiblist \to \everystarttext
+\let\ifbibinteractionelse\doifbibinteractionelse
+
\protect \endinput
diff --git a/tex/context/base/blob-ini.lua b/tex/context/base/blob-ini.lua
index b97485b1b..4debaf94c 100644
--- a/tex/context/base/blob-ini.lua
+++ b/tex/context/base/blob-ini.lua
@@ -74,7 +74,7 @@ function blobs.dispose(t)
end
end
-function blobs.append(t,str) -- will be link nodes.link
+function blobs.append(t,str) -- compare concat and link
local typ = type(str)
local dummy = nil
if typ == "number" then
diff --git a/tex/context/base/buff-ini.lua b/tex/context/base/buff-ini.lua
index 7098679ca..11d7cc9f6 100644
--- a/tex/context/base/buff-ini.lua
+++ b/tex/context/base/buff-ini.lua
@@ -13,21 +13,23 @@ local trace_visualize = false trackers.register("buffers.visualize", function(v
local report_buffers = logs.reporter("buffers","usage")
local report_grabbing = logs.reporter("buffers","grabbing")
+local context, commands = context, commands
+
local concat = table.concat
local type, next = type, next
local sub, format, match, find = string.sub, string.format, string.match, string.find
-local count, splitlines = string.count, string.splitlines
+local count, splitlines, validstring = string.count, string.splitlines, string.valid
-local variables = interfaces.variables
+local variables = interfaces.variables
local settings_to_array = utilities.parsers.settings_to_array
-local ctxcatcodes = tex.ctxcatcodes
-local txtcatcodes = tex.txtcatcodes
+local catcodenumbers = catcodes.numbers
-buffers = { }
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+buffers = buffers or { }
local buffers = buffers
-local context = context
local cache = { }
@@ -100,14 +102,17 @@ commands.assignbuffer = assign
local P, patterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match
+local anything = patterns.anything
+local alwaysmatched = patterns.alwaysmatched
+
local function countnesting(b,e)
local n
local g = P(b) / function() n = n + 1 end
+ P(e) / function() n = n - 1 end
- + patterns.anything
- local p = patterns.alwaysmatched / function() n = 0 end
+ + anything
+ local p = alwaysmatched / function() n = 0 end
* g^0
- * patterns.alwaysmatched / function() return n end
+ * alwaysmatched / function() return n end
return p
end
@@ -150,12 +155,10 @@ function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe
else
if continue then
dn = dn .. sub(bufferdata,2,-2) -- no \r, \n is more generic
+ elseif dn == "" then
+ dn = sub(bufferdata,2,-2)
else
- if dn == "" then
- dn = sub(bufferdata,2,-2)
- else
- dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic
- end
+ dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic
end
local last = sub(dn,-1)
if last == "\n" or last == "\r" then -- \n is unlikely as \r is the endlinechar
@@ -184,7 +187,7 @@ function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe
end
end
assign(name,dn,catcodes)
- commands.testcase(more)
+ commands.doifelse(more)
end
-- The optional prefix hack is there for the typesetbuffer feature and
@@ -232,12 +235,12 @@ end
function commands.getbuffer(name)
local str = getcontent(name)
if str ~= "" then
- context.viafile(str)
+ context.viafile(str,format("buffer.%s",validstring(name,"noname")))
end
end
function commands.getbuffermkvi(name) -- rather direct !
- context.viafile(resolvers.macros.preprocessed(getcontent(name)))
+ context.viafile(resolvers.macros.preprocessed(getcontent(name)),format("buffer.%s.mkiv",validstring(name,"noname")))
end
function commands.gettexbuffer(name)
@@ -265,7 +268,7 @@ function commands.getbufferctxlua(name)
end
function commands.doifelsebuffer(name)
- commands.testcase(exists(name))
+ commands.doifelse(exists(name))
end
-- This only used for mp buffers and is a kludge. Don't change the
diff --git a/tex/context/base/buff-ini.mkiv b/tex/context/base/buff-ini.mkiv
index 239a274c0..5f9d1d1e6 100644
--- a/tex/context/base/buff-ini.mkiv
+++ b/tex/context/base/buff-ini.mkiv
@@ -199,4 +199,28 @@
\def\getbufferdata[#1]{\buff_get_stored_indeed{#1}}
+%D This is a weird one, moved from cont-new. Do we really need it? If not
+%D it will go away.
+
+\bgroup \permitcircumflexescape
+
+\obeylines % don't remove %'s !
+
+\gdef\collapsedspace#1%
+ {\ifx#1^^M%
+ \expandafter\collapsedspace
+ \else
+ \space
+ \expandafter#1%
+ \fi}
+
+\unexpanded\gdef\collapsespaces
+ {\prependtoksonce\relax\to\everyeof%
+ \ignorelines%
+ \ignoretabs%
+ \let\obeyedspace\collapsedspace%
+ \obeyspaces}
+
+\egroup
+
\protect \endinput
diff --git a/tex/context/base/buff-par.lua b/tex/context/base/buff-par.lua
index 2015b0bc0..29742f497 100644
--- a/tex/context/base/buff-par.lua
+++ b/tex/context/base/buff-par.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['buff-ini'] = {
+if not modules then modules = { } end modules ['buff-par'] = {
version = 1.001,
comment = "companion to buff-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -6,21 +6,26 @@ if not modules then modules = { } end modules ['buff-ini'] = {
license = "see context related readme files"
}
-local trace_parallel = false trackers.register("buffers.parallel", function(v) trace_parallel = v end)
-
-local report_parallel = logs.reporter("buffers","parallel")
+local context, commands = context, commands
local insert, remove, find, gmatch = table.insert, table.remove, string.find, string.gmatch
local strip, format = string.strip, string.format
-local variables = interfaces.variables
+local trace_parallel = false trackers.register("buffers.parallel", function(v) trace_parallel = v end)
+
+local report_parallel = logs.reporter("buffers","parallel")
+
+local variables = interfaces.variables
+
+local parallel = buffers.parallel or { }
+buffers.parallel = parallel
-buffers.parallel = { } local parallel = buffers.parallel
+local settings_to_array = utilities.parsers.settings_to_array
-local data = { }
+local data = { }
function parallel.define(category,tags)
- local tags = utilities.parsers.settings_to_array(tags)
+ local tags = settings_to_array(tags)
local entries = { }
data[category] = {
tags = tags,
@@ -38,7 +43,7 @@ function parallel.reset(category,tags)
if not tags or tags == "" or tags == variables.all then
tags = table.keys(entries)
else
- tags = utilities.parsers.settings_to_array(tags)
+ tags = settings_to_array(tags)
end
for i=1,#tags do
entries[tags[i]] = {
@@ -76,7 +81,7 @@ function parallel.save(category,tag,content)
end
-- maybe no strip
-- use lpeg
- if find(content,"^%s*%[") then
+ if find(content,"%s*%[") then
local done = false
for label, content in gmatch(content,"%s*%[(.-)%]%s*([^%[]+)") do
if done then
@@ -175,5 +180,5 @@ commands.placeparallel = parallel.place
commands.resetparallel = parallel.reset
function commands.doifelseparallel(category,tags)
- commands.testcase(parallel.hassomecontent(category,tags))
+ commands.doifelse(parallel.hassomecontent(category,tags))
end
diff --git a/tex/context/base/buff-par.mkiv b/tex/context/base/buff-par.mkiv
deleted file mode 100644
index 7d35676bd..000000000
--- a/tex/context/base/buff-par.mkiv
+++ /dev/null
@@ -1,151 +0,0 @@
-%D \module
-%D [ file=buff-par,
-%D version=2010.12.05,
-%D title=\CONTEXT\ Buffer Macros,
-%D subtitle=Parallel,
-%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 Buffer Macros / Parallel}
-
-\registerctxluafile{buff-par}{1.001}
-
-%D This module is developped for Thomas Schmitz as part of
-%D a project.
-
-\unprotect
-
-\letvalue{\??px:}\empty
-
-\def\parallelparameter#1%
- {\csname\??px:%
- \ifcsname\??px:\currentparallel:\currentparallelinstance:#1\endcsname
- \currentparallel:\currentparallelinstance:#1%
- \else\ifcsname\??px:\currentparallel:#1\endcsname
- \currentparallel:#1%
- \else\ifcsname\??px:#1\endcsname
- #1%
- \fi\fi\fi
- \endcsname}
-
-\unexpanded\def\defineparallel
- {\dodoubleargument\dodefineparallel}
-
-\def\dodefineparallel[#1][#2]%
- {\ctxcommand{defineparallel("#1","#2")}%
- \processcommalist[#2]\dododefineparallel
- \setuvalue{\e!start#1}{\dostartparallelset{#1}}%
- \setuvalue{\e!stop #1}{\dostopparallelset}}
-
-\def\dododefineparallel#1%
- {\definebuffer[#1]%%
- \setuvalue{\e!stop#1}{\dowithparallel{#1}}}
-
-\def\dostartparallelset#1%
- {\def\currentparallel{#1}%
- \ctxcommand{nextparallel("\currentparallel")}}
-
-\def\dostopparallelset#1%
- {}
-
-\def\dowithparallel#1% defined moet ook aan de lua kant kunnen
- {\ctxcommand{saveparallel("\currentparallel","#1",buffers.raw("\thedefinedbuffer{#1}"))}}
-
-\unexpanded\def\placeparallel
- {\dotripleempty\doplaceparallel}
-
-\def\doplaceparallel[#1][#2][#3]%
- {\begingroup
- \def\currentparallel{#1}%
- \ctxcommand{placeparallel("\currentparallel","#2","#3")}%
- \endgroup}
-
-% was: \parallelparameter\c!command}
-
-\def\doflushparallel#1#2#3#4#5% {instance}{status}{line}{label}{content}
- {\begingroup
- \def\currentparallelinstance{#1}%
- \def\currentparallelnumber {#2}%
- \def\currentparallelline {#3}%
- \def\currentparallellabel {#4}%
- \def\currentparallelcontent {#5}%
- \ifcase#2\relax
- \expandafter\noflushparalleldefault
- \or
- \expandafter\doflushparalleldefault
- \fi
- \endgroup}
-
-\def\noflushparalleldefault{}
-\def\doflushparalleldefault{\directsetup{\parallelparameter\c!setups}}
-
-\startsetups parallel:place:default
- \hangafter\plusone
- \hangindent4em
- \dontleavehmode
- \hbox to 3em \bgroup
- \hss
- \bf
- \doifsomething \currentparallellabel {
- \textreference[\currentparallellabel]{\currentparallelline}
- }
- \currentparallelline
- \quad
- \egroup
- \currentparallelcontent
- \par
-\stopsetups
-
-\unexpanded\def\setupparallel
- {\dotripleempty\dosetupparallel}
-
-\def\dosetupparallel[#1][#2][#3]%
- {\ifthirdargument
- \getparameters[\??px:#1:#2:][#3]%
- \else\ifsecondargument
- \getparameters[\??px:#1:][#2]%
- \else
- \getparameters[\??px:][#1]% maybe no : here
- \fi\fi}
-
-\setupparallel
-% [\c!command=\doflushparalleldefault]
- [\c!setups=parallel:place:default]
-
-\def\doifelseparallel#1#2%
- {\cldcontext{commands.doifelseparallel("#1","#2")}}
-
-\def\resetparallel
- {\dodoubleempty\doresetparallel}
-
-\def\resetparallel[#1][#2]%
- {\ctxcommand{resetparallel("#1","#2"))}}
-
-% default
-
-% \def\doflushparalleldefault#1#2#3#4% todo: setups instead
-% {\ifcase#1\or
-% \begingroup
-% \hangafter1
-% \hangindent4em
-% \dontleavehmode
-% \hbox to 3em{\hss\bf\doifsomething{#3}{\textreference[#3]{#2}}#2\quad}#4\par
-% \endgroup
-% \fi}
-
-\protect \endinput
-
-% \def\dododefineparallel#1%
-% {\setuvalue{\e!stop #1}{}%
-% \setuvalue{\e!start#1}{\dostartparallel{#1}}}
-%
-% \def\dostartparallel#1%
-% {\grabuntil{\e!stop#1}{\dododostartparallel{#1}}}
-%
-% \def\dododostartparallel#1#2%
-% {\ctxcommand{saveparallel("\currentparallel","#1",\!!bs\detokenize{#2}\!!es)}}
diff --git a/tex/context/base/buff-par.mkvi b/tex/context/base/buff-par.mkvi
new file mode 100644
index 000000000..404fa8ef3
--- /dev/null
+++ b/tex/context/base/buff-par.mkvi
@@ -0,0 +1,131 @@
+%D \module
+%D [ file=buff-par,
+%D version=2010.12.05,
+%D title=\CONTEXT\ Buffer Macros,
+%D subtitle=Parallel,
+%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 Buffer Macros / Parallel}
+
+\registerctxluafile{buff-par}{1.001}
+
+%D This module is developped for Thomas Schmitz as part of a project. There is
+%D no documentation yet.
+%D
+%D \starttyping
+%D \defineparallel[main][one,two]
+%D
+%D \startmain
+%D \startone
+%D first 1
+%D [reference] first 2
+%D first 3
+%D \stopone
+%D \starttwo
+%D second 1
+%D \stoptwo
+%D \stopmain
+%D
+%D \placeparallel[main][one,two][criterium=all]
+
+%D criterium=all start=<number> n=<number>
+
+\unprotect
+
+\installcorenamespace{parallel}
+
+\installcommandhandler \??parallel {parallel} \??parallel
+
+\setupparallel
+ [\c!setups=parallel:place:default]
+
+\let\buff_parallel_define_saved\defineparallel
+
+\unexpanded\def\defineparallel
+ {\dodoubleargument\buff_parallel_define}
+
+\def\buff_parallel_define[#name][#instances]%
+ {\buff_parallel_define_saved[#name]
+ \ctxcommand{defineparallel("#name","#instances")}%
+ \processcommalist[#instances]\buff_parallel_define_instance
+ \setuevalue{\e!start#name}{\buff_parallel_start{#name}}%
+ \setuevalue{\e!stop #name}{\buff_parallel_stop}}
+
+\def\buff_parallel_define_instance#instance%
+ {\normalexpanded{\buff_parallel_define_saved[#instance][\currentparallel]}%
+ \definebuffer[#instance]%
+ \setuevalue{\e!stop#instance}{\buff_parallel_save{#instance}}}
+
+\unexpanded\def\buff_parallel_start#name%
+ {\pushmacro\currentparallel
+ \edef\currentparallel{#name}%
+ \ctxcommand{nextparallel("\currentparallel")}}
+
+\unexpanded\def\buff_parallel_stop
+ {\popmacro\currentparallel}
+
+\unexpanded\def\buff_parallel_save#instance% defined moet ook aan de lua kant kunnen
+ {\ctxcommand{saveparallel("\currentparallel","#instance",buffers.raw("\thedefinedbuffer{#instance}"))}}
+
+\unexpanded\def\placeparallel
+ {\dotripleempty\buff_parallel_place}
+
+\def\buff_parallel_place[#name][#instance][#settings]%
+ {\begingroup
+ \edef\currentparallel{#name}%
+ \ctxcommand{placeparallel("\currentparallel","#instance","#settings")}% -- todo: pass options as k/v
+ \endgroup}
+
+\def\doflushparallel#instance#status#line#label#content% called at lua end
+ {\begingroup
+ \def\currentparallelinstance{#instance}%
+ \def\currentparallelnumber {#status}%
+ \def\currentparallelline {#line}%
+ \def\currentparallellabel {#label}%
+ \def\currentparallelcontent {#content}%
+ \ifcase#status\relax
+ \expandafter\buff_parallel_flush_nop
+ \or
+ \expandafter\buff_parallel_flush_yes
+ \fi
+ \endgroup}
+
+\def\buff_parallel_flush_nop
+ {}
+
+\def\buff_parallel_flush_yes
+ {\directsetup{\namedparallelparameter\currentparallelinstance\c!setups}}
+
+\unexpanded\def\doifelseparallel#name#instance%
+ {\ctxcommand{doifelseparallel("#name","#instance")}}
+
+\unexpanded\def\resetparallel
+ {\dodoubleempty\buff_parallel_reset}
+
+\def\buff_parallel_reset[#name][#instance]%
+ {\ctxcommand{resetparallel("#name","#instance"))}}
+
+\startsetups parallel:place:default
+ \hangafter\plusone
+ \hangindent4em
+ \dontleavehmode
+ \hbox to 3em \bgroup
+ \hss
+ \bf
+ \doifsomething \currentparallellabel {
+ \textreference[\currentparallellabel]{\currentparallelline}
+ }
+ \currentparallelline
+ \quad
+ \egroup
+ \currentparallelcontent
+ \par
+\stopsetups
+
+\protect \endinput
diff --git a/tex/context/base/buff-ver.lua b/tex/context/base/buff-ver.lua
index 004d89858..5748d9298 100644
--- a/tex/context/base/buff-ver.lua
+++ b/tex/context/base/buff-ver.lua
@@ -18,6 +18,8 @@ local concat = table.concat
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 context, commands = context, commands
+
local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end)
local report_visualizers = logs.reporter("buffers","visualizers")
@@ -30,7 +32,6 @@ visualizers.specifications = specifications
local tabtospace = utilities.strings.tabtospace
local variables = interfaces.variables
local settings_to_array = utilities.parsers.settings_to_array
-local verbatim = context.verbatim
local variables = interfaces.variables
local findfile = resolvers.findfile
local addsuffix = file.addsuffix
@@ -52,6 +53,7 @@ local dodisplayverbatimemptyline = context.dodisplayverbatimemptyline
local dodisplayverbatimstart = context.dodisplayverbatimstart
local dodisplayverbatimstop = context.dodisplayverbatimstop
+local verbatim = context.verbatim
local doverbatimspace = context.doverbatimspace
local CargOne = Carg(1)
@@ -688,7 +690,7 @@ local getlines = buffers.getlines
-- interface
function commands.doifelsevisualizer(name)
- commands.testcase(specifications[lower(name)])
+ commands.doifelse(specifications[lower(name)])
end
commands.loadvisualizer = visualizers.load
diff --git a/tex/context/base/buff-ver.mkiv b/tex/context/base/buff-ver.mkiv
index 5336c4458..d18883faf 100644
--- a/tex/context/base/buff-ver.mkiv
+++ b/tex/context/base/buff-ver.mkiv
@@ -70,21 +70,22 @@
\csname\??typingspace\typeparameter\c!space\endcsname
\relax\the\everyinitializeverbatim\relax}
+\unexpanded\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini)
+ {\buff_verbatim_initialize_type_one
+ \buff_verbatim_initialize_type_two}
+
\let\buff_verbatim_set_line_margin\relax
\def\buff_verbatim_set_line_margin_indeed
- {\getpagestatus
- \hskip\ifrightpage\typingparameter\c!oddmargin\else\typingparameter\c!evenmargin\fi\relax}
+ {\hskip\doifoddpageelse{\typingparameter\c!oddmargin}{\typingparameter\c!evenmargin}\relax}
\def\buff_verbatim_check_margins
{\scratchskip\typingparameter\c!oddmargin\relax
- \ifzeropt\scratchskip
- \else
+ \ifzeropt\scratchskip \else
\let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
\fi
\scratchskip\typingparameter\c!evenmargin\relax
- \ifzeropt\scratchskip
- \else
+ \ifzeropt\scratchskip \else
\let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
\fi
\ifx\buff_verbatim_set_line_margin\relax
@@ -331,7 +332,7 @@
\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\specialstretchedspace{\hskip.5\interwordspace\s!plus.125\interwordstretch\relax} % more but not less
\unexpanded\def\specialcontrolspace {\hskip\zeropoint\hbox{\normalcontrolspace}\hskip\zeropoint\relax}
\unexpanded\def\obeyhyphens
@@ -369,7 +370,7 @@
\let\inlinemathmarker \textdollar
\def\displaymathmarker{\textdollar\textdollar}
-\def\buff_verbatim_special_type#1#2%
+\def\buff_verbatim_special_type#1#2#% # gobbles spaces
{\dontleavehmode\bgroup
\buff_verbatim_initialize_type_one
\catcode\leftbraceasciicode \begingroupcatcode
@@ -390,6 +391,8 @@
\unexpanded\def\astype{\bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken}
+\unexpanded\def\asciistr#1{\dontleavehmode{\verbatimfont\detokenize{#1}}} % use in some old styles
+
%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.
@@ -641,9 +644,9 @@
\c!text=\v!no,
\c!style=\tt,
\c!indentnext=\v!yes,
- \c!margin=\!!zeropoint,
- \c!evenmargin=\!!zeropoint,
- \c!oddmargin=\!!zeropoint,
+ \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,
@@ -836,4 +839,9 @@
% \usevisualizerstyleandcolor\c!style\c!color
% \let\next}
+\appendtoks
+ \def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize
+ \def\tex #1{\letterbackslash#1}%
+\to \everysimplifycommands
+
\protect \endinput
diff --git a/tex/context/base/catc-ctx.mkiv b/tex/context/base/catc-ctx.mkiv
index bd5c16d69..ddade7f52 100644
--- a/tex/context/base/catc-ctx.mkiv
+++ b/tex/context/base/catc-ctx.mkiv
@@ -128,11 +128,18 @@
% for the moment here:
-\def\starttexcode
+\normalprotected\def\starttexcode
{\pushcatcodetable
\catcodetable\prtcatcodes}
-\def\stoptexcode
+\normalprotected\def\stoptexcode
+ {\popcatcodetable}
+
+\normalprotected\def\startcontextcode
+ {\pushcatcodetable
+ \catcodetable\ctxcatcodes}
+
+\normalprotected\def\stopcontextcode
{\popcatcodetable}
\endinput
diff --git a/tex/context/base/catc-def.mkiv b/tex/context/base/catc-def.mkiv
index 26e8cb11e..cfbaed171 100644
--- a/tex/context/base/catc-def.mkiv
+++ b/tex/context/base/catc-def.mkiv
@@ -123,7 +123,7 @@
%D shortcuts to their character representation.
\chardef \^ = \circumflexasciicode
-\chardef \_ = \underscoreasciicode % but way too wide in lm, so ... until that's fixed:
+\chardef \_ = \underscoreasciicode
\chardef \& = \ampersandasciicode
\chardef \% = \commentasciicode
\chardef \# = \hashasciicode
@@ -133,8 +133,9 @@
\chardef \\ = \backslashasciicode
\chardef \| = \barasciicode
-%def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}}
-\def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}} % this will become a \chardef
+% way too wide in lm, so one can also use:
+%
+% \def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}} % this will become a \chardef
%D From now on we can use the protection mechanisms.
diff --git a/tex/context/base/catc-ini.lua b/tex/context/base/catc-ini.lua
index b2c793a6a..d4f9b65af 100644
--- a/tex/context/base/catc-ini.lua
+++ b/tex/context/base/catc-ini.lua
@@ -6,8 +6,6 @@ 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 { }
@@ -15,26 +13,29 @@ catcodes.names = catcodes.names or { }
storage.register("catcodes/numbers", catcodes.numbers, "catcodes.numbers")
storage.register("catcodes/names", catcodes.names, "catcodes.names")
+local numbers = catcodes.numbers
+local names = catcodes.names
+
-- this only happens at initime
function catcodes.register(name,number)
- catcodes.numbers[name] = number
- local cnn = catcodes.names[number]
+ numbers[name] = number
+ local cnn = names[number]
if cnn then
cnn[#cnn+1] = name
else
- catcodes.names[number] = { name }
+ names[number] = { name }
end
- tex[name] = number
+ tex[name] = number -- downward compatible
end
-- this only happens at runtime
-for k, v in next, catcodes.numbers do
- tex[k] = v
+for k, v in next, numbers do
+ tex[k] = v -- downward compatible
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)
+table.setmetatableindex(numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end)
+table.setmetatableindex(names, function(t,k) if type(k) == "string" then t[k] = k return k end end)
diff --git a/tex/context/base/catc-ini.mkiv b/tex/context/base/catc-ini.mkiv
index 26c3ceee9..791ce31c4 100644
--- a/tex/context/base/catc-ini.mkiv
+++ b/tex/context/base/catc-ini.mkiv
@@ -87,6 +87,17 @@
\xdef\outputnewlinechar{^^J}%
\endgroup}
+%D We predefine some prefixes ahead of syst-aux and mult-sys. We reserve 8 slots
+%D for catcodes.
+
+\def\??catcodelet {1>>} % let : \let
+\def\??catcodedef {2>>} % def : \def
+\def\??catcodeued {3>>} % ued : \unexpanded\def
+\def\??catcodeget {4>>} % \meaning
+
+\def\??catcodetablet{5>>}
+\def\??catcodetablen{6>>}
+
\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
@@ -94,7 +105,7 @@
\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
+ \expandafter\xdef\csname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging
\newconstant#1%
#1\c_syst_catcodes_n
\ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}}
@@ -151,12 +162,7 @@
\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.
-
-\def\??ql{@@ql} % let : \let
-\def\??qd{@@qd} % def : \def
-\def\??qu{@@qu} % ued : \unexpanded\def
-\def\??qm{@@qm} % \meaning
+%D faster.
\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a}
\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a}
@@ -167,46 +173,46 @@
\def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b}
\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
+ {\ifcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\else
\expandafter\syst_catcodes_let_c
\fi}
\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
+ {\ifcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\else
\expandafter\syst_catcodes_def_c
\fi}
\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
+ {\ifcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\else
\expandafter\syst_catcodes_ued_c
\fi}
\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}%
+ {\expandafter\gdef\csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter
+ {\expandafter\let\csname\??catcodeget\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}
+ \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
\def\syst_catcodes_def_c % only first time (we could use \normalexpanded here)
- {\expandafter\gdef\csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ {\expandafter\gdef\csname\??catcodedef\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}}%
+ {\expandafter\def\csname\??catcodeget\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}
+ \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\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\gdef\csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\expandafter##\expandafter1\expandafter
- {\expandafter\normalprotected\expandafter\def\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ {\expandafter\normalprotected\expandafter\def\csname\??catcodeget\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}
+ \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
\def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b}
@@ -227,8 +233,8 @@
\newconstant\defaultcatcodetable
\def\catcodecommand#1%
- {\csname\??qm:\number
- \ifcsname\??qm:\number\currentcatcodetable:\number#1\endcsname
+ {\csname\??catcodeget\number
+ \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname
\currentcatcodetable \else \defaultcatcodetable
\fi
:\number#1\endcsname}
@@ -251,13 +257,13 @@
\normalprotected\def\pushcatcodetable
{\advance\c_syst_catcodes_level\plusone
\syst_catcodes_trace_push
- \expandafter\chardef\csname\??qm:t:\number\c_syst_catcodes_level\endcsname\currentcatcodetable}
+ \expandafter\chardef\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname\currentcatcodetable}
\normalprotected\def\popcatcodetable
{\ifcase\c_syst_catcodes_level
\syst_catcodes_trace_nesting_error
\else
- \expandafter\catcodetable\csname\??qm:t:\number\c_syst_catcodes_level\endcsname
+ \expandafter\catcodetable\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname
\syst_catcodes_trace_pop
\advance\c_syst_catcodes_level\minusone
\fi}
@@ -269,7 +275,7 @@
\normalprotected\def\restorecatcodes % takes previous level
{\ifnum\c_syst_catcodes_level>\plusone
- \expandafter\catcodetable\csname\??qm:t:\number\numexpr\c_syst_catcodes_level-1\relax\endcsname
+ \expandafter\catcodetable\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname
\fi}
% \newtoks\everycatcodetable
@@ -294,14 +300,14 @@
\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
+ \csname\??catcodetablen\number\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname
\else
-%
\fi}
\def\catcodetablename
{\ifnum\currentcatcodetable>\zerocount
- \csname\??qm:n:\number\currentcatcodetable\endcsname
+ \csname\??catcodetablen\number\currentcatcodetable\endcsname
\else
-%
\fi}
diff --git a/tex/context/base/char-cjk.lua b/tex/context/base/char-cjk.lua
index b077f4a3e..3d7de1423 100644
--- a/tex/context/base/char-cjk.lua
+++ b/tex/context/base/char-cjk.lua
@@ -12,7 +12,8 @@ local floor = math.floor
local format = string.format
local utfchar = utf.char
-local ranges = characters.ranges
+local ranges = characters.ranges
+local allocate = utilities.storage.allocate
-- Hangul Syllable
@@ -209,7 +210,7 @@ local remapped = { -- this might be merged into char-def.lua
[0x11C2] = 0x314E, -- H
}
-characters.hangul = {
+characters.hangul = allocate {
decomposed = decomposed,
description = description,
leadconsonant = leadconsonant,
@@ -226,24 +227,6 @@ local hangul_syllable_basetable = {
linebreak = "h2",
}
---~ local hangul_syllable_metatable = {
---~ __index = function(t,k)
---~ local u = t.unicodeslot
---~ if k == "fscode" then
---~ -- no need to cache this as we normally use fscodes
---~ return leadconsonant(u)
---~ elseif k == "shcode" then
---~ return { decomposed(u) }
---~ elseif k == "specials" then
---~ return { "char", decomposed(u) }
---~ elseif k == "description" then
---~ return description(u)
---~ else
---~ return hangul_syllable_basetable[k]
---~ end
---~ end
---~ }
-
local hangul_syllable_metatable = {
__index = function(t,k)
local u = t.unicodeslot
diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua
index 804468c2d..6c73cf008 100644
--- a/tex/context/base/char-def.lua
+++ b/tex/context/base/char-def.lua
@@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['char-def'] = {
comment = "companion to char-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+ license = "see context related readme files",
+ dataonly = true,
}
--[[
@@ -56832,6 +56833,16 @@ characters.data={
description="OVERLINE",
direction="on",
linebreak="al",
+ mathspec={
+ {
+ class="topaccent",
+ name="overbar",
+ },
+ {
+ class="botaccent",
+ name="underbar",
+ },
+ },
specials={ "compat", 0x0020, 0x0305 },
unicodeslot=0x203E,
},
@@ -57244,6 +57255,8 @@ characters.data={
description="SUPERSCRIPT PLUS SIGN",
direction="es",
linebreak="al",
+ mathclass="binary",
+ mathname ="positivesign",
specials={ "super", 0x002B },
unicodeslot=0x207A,
},
@@ -57252,6 +57265,8 @@ characters.data={
description="SUPERSCRIPT MINUS",
direction="es",
linebreak="al",
+ mathclass="binary",
+ mathname ="negativesign",
specials={ "super", 0x2212 },
unicodeslot=0x207B,
},
@@ -58669,7 +58684,7 @@ characters.data={
description="TURNED AMPERSAND",
direction="on",
linebreak="al",
- mathclass="bin",
+ mathclass="binary",
mathname="upand",
unicodeslot=0x214B,
},
@@ -60887,11 +60902,11 @@ characters.data={
linebreak="ai",
mathspec={
{
- class="bin",
+ class="binary",
name="vee",
},
{
- class="bin",
+ class="binary",
name="lor",
},
},
@@ -60932,15 +60947,16 @@ characters.data={
description="INTEGRAL",
direction="on",
linebreak="ai",
+ mathclass="limop",
mathspec={
{
- class="nothing",
- name="intop",
- },
- {
class="limop",
name="int",
},
+ {
+ class="nothing",
+ name="intop",
+ },
},
unicodeslot=0x222B,
},
@@ -60951,15 +60967,16 @@ characters.data={
description="DOUBLE INTEGRAL",
direction="on",
linebreak="ai",
+ mathclass="limop",
mathspec={
{
- class="nothing",
- name="iintop",
- },
- {
class="limop",
name="iint",
},
+ {
+ class="nothing",
+ name="iintop",
+ },
},
specials={ "compat", 0x222B, 0x222B },
unicodeslot=0x222C,
@@ -60969,15 +60986,16 @@ characters.data={
description="TRIPLE INTEGRAL",
direction="on",
linebreak="al",
+ mathclass="limop",
mathspec={
{
- class="nothing",
- name="iiintop",
- },
- {
class="limop",
name="iiint",
},
+ {
+ class="nothing",
+ name="iiintop",
+ },
},
specials={ "compat", 0x222B, 0x222B, 0x222B },
unicodeslot=0x222D,
@@ -62402,7 +62420,7 @@ characters.data={
description="NORMAL SUBGROUP OF",
direction="on",
linebreak="al",
- mathclass="bin",
+ mathclass="binary",
mirror=0x22B3,
unicodeslot=0x22B2,
},
@@ -62412,7 +62430,7 @@ characters.data={
description="CONTAINS AS NORMAL SUBGROUP",
direction="on",
linebreak="al",
- mathclass="bin",
+ mathclass="binary",
mirror=0x22B2,
unicodeslot=0x22B3,
},
@@ -68388,6 +68406,8 @@ characters.data={
description="BLACK UP-POINTING TRIANGLE",
direction="on",
linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangle",
unicodeslot=0x25B2,
},
[0x25B3]={
@@ -68432,7 +68452,7 @@ characters.data={
description="BLACK RIGHT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
- mathclass="bin",
+ mathclass="binary",
mathname="blacktriangleright",
unicodeslot=0x25B6,
},
@@ -68443,7 +68463,7 @@ characters.data={
description="WHITE RIGHT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
- mathclass="bin",
+ mathclass="binary",
mathname="triangleright",
unicodeslot=0x25B7,
},
@@ -68452,8 +68472,6 @@ characters.data={
description="BLACK RIGHT-POINTING SMALL TRIANGLE",
direction="on",
linebreak="al",
- mathclass="bin",
- mathname="blacktriangleleft",
unicodeslot=0x25B8,
},
[0x25B9]={
@@ -68486,6 +68504,8 @@ characters.data={
description="BLACK DOWN-POINTING TRIANGLE",
direction="on",
linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangledown",
unicodeslot=0x25BC,
},
[0x25BD]={
@@ -68495,8 +68515,16 @@ characters.data={
description="WHITE DOWN-POINTING TRIANGLE",
direction="on",
linebreak="ai",
- mathclass="binary",
- mathname="bigtriangledown",
+ mathspec={
+ {
+ class="binary",
+ name="triangledown",
+ },
+ {
+ class="binary",
+ name="bigtriangledown",
+ },
+ },
unicodeslot=0x25BD,
},
[0x25BE]={
@@ -68521,6 +68549,8 @@ characters.data={
description="BLACK LEFT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangleleft",
unicodeslot=0x25C0,
},
[0x25C1]={
@@ -68530,7 +68560,7 @@ characters.data={
description="WHITE LEFT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
- mathclass="bin",
+ mathclass="binary",
mathname="triangleleft",
unicodeslot=0x25C1,
},
diff --git a/tex/context/base/char-enc.lua b/tex/context/base/char-enc.lua
index ef6805e54..048837eec 100644
--- a/tex/context/base/char-enc.lua
+++ b/tex/context/base/char-enc.lua
@@ -1,9 +1,10 @@
-if not modules then modules = { } end modules ['char-syn'] = {
+if not modules then modules = { } end modules ['char-enc'] = {
version = 1.001,
comment = "companion to char-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
+ -- dataonly = true,
}
-- Thanks to tex4ht for these mappings.
@@ -144,25 +145,25 @@ characters.synonyms = allocate { -- afm mess
Yen = 0x00A5,
}
---~ if not characters.enccodes then
---~
---~ local enccodes = { } characters.enccodes = enccodes
---~
---~ for unicode, data in next, characters.data do
---~ local encname = data.adobename or data.contextname
---~ if encname then
---~ enccodes[encname] = unicode
---~ end
---~ end
---~
---~ for name, unicode in next, characters.synonyms do
---~ if not enccodes[name] then enccodes[name] = unicode end
---~ end
---~
---~
---~ end
---~
---~ storage.register("characters.enccodes", characters.enccodes, "characters.enccodes")
+-- if not characters.enccodes then
+--
+-- local enccodes = { } characters.enccodes = enccodes
+--
+-- for unicode, data in next, characters.data do
+-- local encname = data.adobename or data.contextname
+-- if encname then
+-- enccodes[encname] = unicode
+-- end
+-- end
+--
+-- for name, unicode in next, characters.synonyms do
+-- if not enccodes[name] then enccodes[name] = unicode end
+-- end
+--
+--
+-- end
+--
+-- storage.register("characters.enccodes", characters.enccodes, "characters.enccodes")
-- As this table is seldom used, we can delay its definition. Beware, this means
-- that table.print would not work on this file unless it is accessed once. This
diff --git a/tex/context/base/char-ent.lua b/tex/context/base/char-ent.lua
index d2ac22bbf..ef55be7e4 100644
--- a/tex/context/base/char-ent.lua
+++ b/tex/context/base/char-ent.lua
@@ -1,15 +1,14 @@
-if not modules then modules = { } end modules ['math-ent'] = {
+if not modules then modules = { } end modules ['char-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",
+ dataonly = true,
}
-- 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
diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua
index 244b8d2a7..778035ff4 100644
--- a/tex/context/base/char-ini.lua
+++ b/tex/context/base/char-ini.lua
@@ -11,10 +11,9 @@ if not modules then modules = { } end modules ['char-ini'] = {
-- 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 ustring, utf = unicode.ustring, unicode.utf8
local concat, unpack, tohash = table.concat, table.unpack, table.tohash
local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset
local format, lower, gsub, match, gmatch = string.format, string.lower, string.gsub, string.match, string.match, string.gmatch
@@ -28,8 +27,8 @@ local texsetsfcode = tex.setsfcode
local texsetcatcode = tex.setcatcode
local contextsprint = context.sprint
-local ctxcatcodes = tex.ctxcatcodes
-local texcatcodes = tex.texcatcodes
+local ctxcatcodes = catcodes.numbers.ctxcatcodes
+local texcatcodes = catcodes.numbers.texcatcodes
local setmetatableindex = table.setmetatableindex
@@ -48,7 +47,6 @@ loaded!</p>
characters = characters or { }
local characters = characters
-
local data = characters.data
if data then
@@ -455,28 +453,39 @@ table we derive a few more.</p>
if not characters.fallbacks then
- -- we could the definition by using a metatable
-
- characters.fallbacks = { }
- characters.directions = { }
+ characters.fallbacks = { } -- not than many
- local fallbacks = characters.fallbacks
- local directions = characters.directions
+ local fallbacks = characters.fallbacks
- for k,v in next, data do
- local specials = v.specials
- if specials and specials[1] == "compat" and specials[2] == 0x0020 and specials[3] then
+ for k, d in next, data do
+ local specials = d.specials
+ if specials and specials[1] == "compat" and specials[2] == 0x0020 then
local s = specials[3]
- fallbacks[k] = s
- fallbacks[s] = k
+ if s then
+ fallbacks[k] = s
+ fallbacks[s] = k
+ end
end
- directions[k] = v.direction
end
end
-storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such
-storage.register("characters/directions", characters.directions, "characters.directions")
+storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such
+
+characters.directions = { }
+
+setmetatableindex(characters.directions,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.direction
+ if v then
+ t[k] = v
+ return v
+ end
+ end
+ t[k] = false -- maybe 'l'
+ return v
+end)
--[[ldx--
<p>The <type>context</type> namespace is used to store methods and data
@@ -488,7 +497,7 @@ which is rather specific to <l n='context'/>.</p>
use the table. After all, we have this information available anyway.</p>
--ldx]]--
-function characters.makeactive(n,name) -- let ?
+function characters.makeactive(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
@@ -503,7 +512,7 @@ function tex.uprint(c,n)
end
end
-local temphack = tohash {
+local forbidden = tohash { -- at least now
0x00A0,
0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D,
0x202F,
@@ -539,12 +548,10 @@ function characters.define(tobelettered, tobeactivated) -- catcodetables
else
contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u))) -- has no s
end
- elseif is_command[category] then
-if not temphack[u] then
+ elseif is_command[category] and not forbidden[u] then
contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}")
a = a + 1
activated[a] = u
-end
end
end
end
@@ -632,15 +639,17 @@ function characters.setcodes()
end
else
local lc, uc = chr.lccode, chr.uccode
- if not lc then chr.lccode, lc = code, code end
- if not uc then chr.uccode, uc = code, code end
- texsetcatcode(code,11) -- letter
- if type(lc) == "table" then
+ if not lc then
+ chr.lccode, lc = code, code
+ elseif type(lc) == "table" then
lc = code
end
- if type(uc) == "table" then
+ if not uc then
+ chr.uccode, uc = code, code
+ elseif type(uc) == "table" then
uc = code
end
+ texsetcatcode(code,11) -- letter
texsetlccode(code,lc,uc)
if cc == "lu" then
texsetsfcode(code,999)
@@ -815,8 +824,7 @@ function characters.unicodechar(asked)
if n then
return n
elseif type(asked) == "string" then
- asked = gsub(asked," ","")
- return descriptions[asked]
+ return descriptions[asked] or descriptions[gsub(asked," ","")]
end
end
@@ -882,17 +890,21 @@ end
function characters.uccode(n) return uccodes[n] end -- obsolete
function characters.lccode(n) return lccodes[n] end -- obsolete
-function characters.flush(n,direct)
+function characters.safechar(n)
local c = data[n]
if c and c.contextname then
- c = "\\" .. c.contextname
+ return "\\" .. c.contextname
else
- c = utfchar(n)
+ return utfchar(n)
end
- if direct then
- return c
+end
+
+function commands.safechar(n)
+ local c = data[n]
+ if c and c.contextname then
+ contextsprint("\\" .. c.contextname) -- context[c.contextname]()
else
- contextsprint(c)
+ contextsprint(utfchar(n))
end
end
diff --git a/tex/context/base/char-map.lua b/tex/context/base/char-map.lua
index 376ebf343..749da5289 100644
--- a/tex/context/base/char-map.lua
+++ b/tex/context/base/char-map.lua
@@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['char-map'] = {
comment = "companion to char-ini.mkiv",
author = "Hans Hagen & Arthur Reutenauer",
copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+ license = "see context related readme files",
+ dataonly = true,
}
-- not yet used
diff --git a/tex/context/base/char-utf.lua b/tex/context/base/char-utf.lua
index a411c2d82..52fdfc0d0 100644
--- a/tex/context/base/char-utf.lua
+++ b/tex/context/base/char-utf.lua
@@ -19,7 +19,7 @@ in special kinds of output (for instance <l n='pdf'/>).</p>
over a string.</p>
--ldx]]--
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
+local utfchar, utfbyte = utf.char, utf.byte
local concat, gmatch, gsub, find = table.concat, string.gmatch, string.gsub, string.find
local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
local allocate = utilities.storage.allocate
@@ -76,6 +76,7 @@ local decomposed = allocate {
["ﬖ"] = "վն",
["ﬗ"] = "մխ",
}
+
characters.decomposed = decomposed
local function initialize() -- maybe only 'mn'
@@ -209,9 +210,13 @@ end
private.set = set
-function private.escape (str) return gsub(str,"(.)", escapes) end
-function private.replace(str) return utfgsub(str,"(.)", low ) end
-function private.revert (str) return utfgsub(str,"(.)", high ) end
+-- function private.escape (str) return gsub(str,"(.)", escapes) end
+-- function private.replace(str) return utfgsub(str,"(.)", low ) end
+-- function private.revert (str) return utfgsub(str,"(.)", high ) end
+
+private.escape = utf.remapper(escapes)
+private.replace = utf.remapper(low)
+private.revert = utf.remapper(high)
for ch in gmatch(special,".") do set(ch) end
@@ -481,6 +486,14 @@ if sequencers then
sequencers.enableaction(textfileactions,"characters.filters.utf.decompose")
end
+ directives.register("filters.utf.collapse", function(v)
+ sequencers[v and "enableaction" or "disableaction"](textfileactions,"characters.filters.utf.collapse")
+ end)
+
+ directives.register("filters.utf.decompose", function(v)
+ sequencers[v and "enableaction" or "disableaction"](textfileactions,"characters.filters.utf.decompose")
+ end)
+
end
--[[ldx--
diff --git a/tex/context/base/chem-ini.lua b/tex/context/base/chem-ini.lua
index 4d47982a2..192953ec9 100644
--- a/tex/context/base/chem-ini.lua
+++ b/tex/context/base/chem-ini.lua
@@ -17,8 +17,8 @@ local report_chemistry = logs.reporter("chemistry")
local context = context
-chemicals = chemicals or { }
-local chemicals = chemicals
+chemistry = chemistry or { }
+local chemistry = chemistry
--[[
<p>The next code is an adaptation of code from Wolfgang Schuster
@@ -62,9 +62,9 @@ local high = Cc("\\high{%s}") * superscript * content
local justtext = (1 - somescript)^1
local parser = Cs((csname + lowhigh + highlow + low + high + sign + any)^0)
-chemicals.moleculeparser = parser -- can be used to avoid functioncall
+chemistry.moleculeparser = parser -- can be used to avoid functioncall
-function chemicals.molecule(str)
+function chemistry.molecule(str)
return lpegmatch(parser,str)
end
diff --git a/tex/context/base/chem-str.lua b/tex/context/base/chem-str.lua
index fb325ccea..db1849c5a 100644
--- a/tex/context/base/chem-str.lua
+++ b/tex/context/base/chem-str.lua
@@ -1,12 +1,15 @@
if not modules then modules = { } end modules ['chem-str'] = {
version = 1.001,
comment = "companion to chem-str.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ author = "Hans Hagen and Alan Braslau",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
--- This module in incomplete and experimental.
+-- The original \PPCHTEX\ code was written in pure \TEX\, although later we made
+-- the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between
+-- \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible
+-- but better implementation, later versions might provide more,
-- We can push snippets into an mp instance.
@@ -26,12 +29,12 @@ local P, R, S, C, Cs, Ct, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct,
local variables = interfaces.variables
local context = context
-chemicals = chemicals or { }
-local chemicals = chemicals
+chemistry = chemistry or { }
+local chemistry = chemistry
-chemicals.instance = "metafun" -- "ppchtex"
-chemicals.format = "metafun"
-chemicals.structures = 0
+chemistry.instance = "metafun" -- "ppchtex"
+chemistry.format = "metafun"
+chemistry.structures = 0
local remapper = {
["+"] = "p",
@@ -52,7 +55,9 @@ local common_keys = {
mid = "fixed", mids = "fixed", midz = "text",
z = "text", rz = "text", mrz = "text", prz = "text", crz = "text",
rt = "text", rtt = "text", rbt = "text", zt = "text", zn = "number",
- mov = "transform", rot = "transform", adj = "transform", dir = "transform", sub = "transform",
+ zbt = "text", zbn = "number", ztt = "text", ztn = "number",
+ mov = "transform", rot = "transform", adj = "transform", sub = "transform",
+ off = "transform",
}
local front_keys = {
@@ -60,9 +65,11 @@ local front_keys = {
sb = "line", msb = "line", psb = "line",
r = "line", pr = "line", mr = "line",
z = "text", mrz = "text", prz = "text",
+ zt = "text", zn = "number",
}
local one_keys = {
+ b = "line", msb = "line", psb = "line",
sb = "line", db = "line", tb = "line",
ep = "line", es = "line", ed = "line", et = "line",
sd = "line", ldd = "line", rdd = "line",
@@ -81,15 +88,16 @@ local syntax = {
one = {
n = 1, max = 8, keys = one_keys,
align = {
- z = { { "r", "r_b", "b", "l_b", "l", "l_t", "t", "r_t" } },
---~ z = { { "r", "r", "b", "l", "l", "l", "t", "r" } },
+ -- z = { { "r", "r_b", "b", "l_b", "l", "l_t", "t", "r_t" } },
+ -- z = { { "r", "r", "b", "l", "l", "l", "t", "r" } },
}
},
three = {
n = 3, max = 3, keys = common_keys,
align = {
mrz = { { "r","b","l" }, { "b","l","t" }, { "l","t","r" }, { "t","r","b" } },
- rz = { { "r","l_b","l_t" }, { "b","l_t","r_t" }, { "l","r_t","r_b" }, { "t","r_b","l_b" } },
+ rz = { { "auto","auto","auto" }, { "auto","auto","auto" }, { "auto","auto","auto" }, { "auto","auto","auto" } },
+ -- rz = { { "r_t","r_b","l" }, { "r_b","l_b","t" }, { "l_b","l_t","r" }, { "l_t","r_t","b" } },
prz = { { "r","l","t" }, { "b","t","r" }, { "l","r","b" }, { "t","b","l" } },
}
},
@@ -97,7 +105,8 @@ local syntax = {
n = 4, max = 4, keys = common_keys,
align = {
mrz = { { "t","r","b","l" }, { "r","b","l","t" }, { "b","l","t","r" }, { "l","t","r","b" } },
- rz = { { "r_t","r_b","l_b","l_t" }, { "r_b","l_b","l_t","r_t" }, { "l_b","l_t","r_t","r_b" }, { "l_t","r_t","r_b","l_b" } },
+ rz = { { "auto","auto","auto","auto" }, { "auto","auto","auto","auto" }, { "auto","auto","auto","auto" }, { "auto","auto","auto","auto" } },
+ -- rz = { { "r_t","r_b","l_b","l_t" }, { "r_b","l_b","l_t","r_t" }, { "l_b","l_t","r_t","r_b" }, { "l_t","r_t","r_b","l_b" } },
prz = { { "r","b","l","t" }, { "b","l","t","r" }, { "l","t","r","b" }, { "t","r","b","l" } },
}
},
@@ -105,7 +114,8 @@ local syntax = {
n = 5, max = 5, keys = common_keys,
align = {
mrz = { { "t","r","b","b","l" }, { "r","b","l","l","t" }, { "b","l","t","r","r" }, { "l","t","r","r","b" } },
- rz = { { "r","r","b","l","t" }, { "b","b","l","t","r" }, { "l","l","t","r","b" }, { "t","t","r","b","l" } },
+ rz = { { "auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto" } },
+ -- rz = { { "r","r","b","l","t" }, { "b","b","l","t","r" }, { "l","l","t","r","b" }, { "t","t","r","b","l" } },
prz = { { "r","b","l","t","t" }, { "b","l","t","r","r" }, { "l","t","r","b","b" }, { "t","r","b","l","l" } },
}
},
@@ -113,7 +123,8 @@ local syntax = {
n = 6, max = 6, keys = common_keys,
align = {
mrz = { { "t","t","r","b","b","l" }, { "r","b","b","l","t","t" }, { "b","b","l","t","t","r" }, { "l","t","t","r","b","b" } },
- rz = { { "r","r","b","l","l","t" }, { "b","b","l","t","t","r" }, { "l","l","t","r","r","b" }, { "t","t","r","b","b","l" } },
+ rz = { { "auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto" } },
+ -- rz = { { "r","r","b","l","l","t" }, { "b","b","l","t","t","r" }, { "l","l","t","r","r","b" }, { "t","t","r","b","b","l" } },
prz = { { "r","b","l","l","t","r" }, { "b","l","t","t","r","b" }, { "l","t","r","r","b","l" }, { "t","r","b","b","l","t" } },
}
},
@@ -121,7 +132,8 @@ local syntax = {
n = 8, max = 8, keys = common_keys,
align = { -- todo
mrz = { { "t","r","r","b","b","l","l","t" }, { "r","b","b","l","l","t","t","r" }, { "b","l","l","t","t","r","r","b" }, { "l","t","t","r","r","b","b","l" } },
- rz = { { "r","r","b","b","l","l","t","t" }, { "b","b","l","l","t","t","r","r" }, { "l","l","t","t","r","r","b","b" }, { "t","t","r","r","b","b","l","l" } },
+ rz = { { "auto","auto","auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto","auto","auto" }, { "auto","auto","auto","auto","auto","auto","auto","auto" } },
+ -- rz = { { "r","r","b","b","l","l","t","t" }, { "b","b","l","l","t","t","r","r" }, { "l","l","t","t","r","r","b","b" }, { "t","t","r","r","b","b","l","l" } },
prz = { { "r","b","b","l","l","t","t","r" }, { "b","l","l","t","t","r","r","b" }, { "l","t","t","r","r","b","b","l" }, { "t","r","r","b","b","l","l","t" } },
}
},
@@ -147,11 +159,11 @@ local syntax = {
local definitions = { }
-function chemicals.undefine(name)
+function chemistry.undefine(name)
definitions[lower(name)] = nil
end
-function chemicals.define(name,spec,text)
+function chemistry.define(name,spec,text)
name = lower(name)
local dn = definitions[name]
if not dn then dn = { } definitions[name] = dn end
@@ -162,7 +174,7 @@ function chemicals.define(name,spec,text)
end
local metacode, variant, keys, bonds, max, txt, textsize, rot, pstack
-local molecule = chemicals.molecule -- or use lpegmatch(chemicals.moleculeparser,...)
+local molecule = chemistry.molecule -- or use lpegmatch(chemistry.moleculeparser,...)
local function fetch(txt)
local st = stack[txt]
@@ -196,35 +208,46 @@ local text = (equal * C(P(1)^0)) + Cc(false)
local pattern =
(amount + Cc(1)) *
- operation *
- special * (
+ Cs(operation/lower) *
+ Cs(special/lower) * (
+-- operation *
+-- special * (
range * Cc(false) * text +
Cc(false) * Cc(false) * set * text +
single * Cc(false) * Cc(false) * text +
Cc(false) * Cc(false) * Cc(false) * text
)
---~ local n, operation, index, upto, set, text = lpegmatch(pattern,"RZ1357")
+-- local n, operation, index, upto, set, text = lpegmatch(pattern,"RZ1357")
---~ print(lpegmatch(pattern,"RZ=x")) 1 RZ false false false x
---~ print(lpegmatch(pattern,"RZ1=x")) 1 RZ 1 false false x
---~ print(lpegmatch(pattern,"RZ1..3=x")) 1 RZ 1 3 false x
---~ print(lpegmatch(pattern,"RZ13=x")) 1 RZ false false table x
+-- print(lpegmatch(pattern,"RZ=x")) -- 1 RZ false false false x
+-- print(lpegmatch(pattern,"RZ1=x")) -- 1 RZ 1 false false x
+-- print(lpegmatch(pattern,"RZ1..3=x")) -- 1 RZ 1 3 false x
+-- print(lpegmatch(pattern,"RZ13=x")) -- 1 RZ false false table x
local function process(spec,text,n,rulethickness,rulecolor,offset)
insert(stack,{ spec=spec, text=text, n=n })
local txt = #stack
local m = #metacode
for i=1,#spec do
- local s = spec[i]
+ local step = spec[i]
+ local s = lower(step)
local d = definitions[s]
if d then
+ if trace_structure then
+ report_chemistry("%s => definition: %s",step,s)
+ end
for i=1,#d do
local di = d[i]
process(di.spec,di.text,1,rulethickness,rulecolor)
end
else
- local rep, operation, special, index, upto, set, text = lpegmatch(pattern,s)
+ local rep, operation, special, index, upto, set, text = lpegmatch(pattern,step)
+ if trace_structure then
+ local set = set and concat(set," ") or "-"
+ report_chemistry("%s => rep: %s, operation: %s, special: %s, index: %s, upto: %s, set: %s, text: %s",
+ step,rep or "-",operation or "-",special and special ~= "" or "-",index or "-",upto or "-",set or "-",text or "-")
+ end
if operation == "pb" then
insert(pstack,variant)
m = m + 1 ; metacode[m] = syntax.pb.direct
@@ -339,7 +362,8 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if not t then txt, t = fetch(txt) end
if t then
t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format('chem_%s_zero("\\chemicaltext{%s}");',operation,t)
+ m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\chemicaltext{%s}");',operation,bonds,index,t)
+ -- m = m + 1 ; metacode[m] = format('chem_%s_zero("\\chemicaltext{%s}");',operation,t)
end
elseif index then
local t = text
@@ -388,8 +412,8 @@ end
--
-- rulethickness in points
-function chemicals.start(settings)
- chemicals.structures = chemicals.structures + 1
+function chemistry.start(settings)
+ chemistry.structures = chemistry.structures + 1
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
@@ -445,63 +469,73 @@ function chemicals.start(settings)
scale = 0.75 * scale/625
--
metacode[#metacode+1] = format("chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) ;",
- chemicals.structures,
+ chemistry.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, { }
+ -- variant, keys, bonds, stack, rot, pstack = "six", { }, 6, { }, 1, { }
+ variant, keys, bonds, stack, rot, pstack = "one", { }, 1, { }, 1, { }
end
-function chemicals.stop()
+function chemistry.stop()
metacode[#metacode+1] = "chem_stop_structure ;"
--
local mpcode = concat(metacode,"\n")
if trace_structure then
report_chemistry("metapost code:\n%s", mpcode)
end
- metapost.graphic(chemicals.instance,chemicals.format,mpcode)
+ metapost.graphic(chemistry.instance,chemistry.format,mpcode)
metacode = nil
end
-function chemicals.component(spec,text,settings)
+function chemistry.component(spec,text,settings)
rulethickness, rulecolor, offset = settings.rulethickness, settings.rulecolor
- local spec = settings_to_array(lower(spec))
+-- local spec = settings_to_array(lower(spec))
+ local spec = settings_to_array(spec)
local text = settings_to_array(text)
metacode[#metacode+1] = "chem_start_component ;"
process(spec,text,1,rulethickness,rulecolor)
metacode[#metacode+1] = "chem_stop_component ;"
end
+statistics.register("chemical formulas", function()
+ if chemistry.structures > 0 then
+ return format("%s chemical structure formulas",chemistry.structures) -- no timing needed, part of metapost
+ end
+end)
+
+-- interfaces
+
+commands.undefinechemical = chemistry.undefine
+commands.definechemical = chemistry.define
+commands.startchemical = chemistry.start
+commands.stopchemical = chemistry.stop
+commands.chemicalcomponent = chemistry.component
+
+-- todo: top / bottom
+
local inline = {
["single"] = "\\chemicalsinglebond", ["-"] = "\\chemicalsinglebond",
- ["double"] = "\\chemicaldoublebond", ["--"] = "\\chemicaldoublebond",
+ ["double"] = "\\chemicaldoublebond", ["--"] = "\\chemicaldoublebond", -- also =? and unicode triple?
["triple"] = "\\chemicaltriplebond", ["---"] = "\\chemicaltriplebond",
["gives"] = "\\chemicalgives", ["->"] = "\\chemicalgives",
["equilibrium"] = "\\chemicalequilibrium", ["<->"] = "\\chemicalequilibrium",
["mesomeric"] = "\\chemicalmesomeric", ["<>"] = "\\chemicalmesomeric",
- ["plus"] = "\\chemicalsplus", ["+"] = "\\chemicalsplus",
- ["minus"] = "\\chemicalsminus",
- ["space"] = "\\chemicalsspace",
+ ["plus"] = "\\chemicalplus", ["+"] = "\\chemicalplus",
+ ["minus"] = "\\chemicalminus",
+ ["space"] = "\\chemicalspace",
}
--- todo: top / bottom
-
-function chemicals.inline(spec)
+function commands.inlinechemical(spec)
local spec = settings_to_array(spec)
for i=1,#spec do
local s = spec[i]
local inl = inline[lower(s)]
if inl then
- context(inl)
+ context(inl) -- could be a fast context.sprint
else
context.chemicalinline(molecule(s))
end
end
end
-
-statistics.register("chemical formulas", function()
- if chemicals.structures > 0 then
- return format("%s chemical structure formulas",chemicals.structures) -- no timing needed, part of metapost
- end
-end)
diff --git a/tex/context/base/chem-str.mkiv b/tex/context/base/chem-str.mkiv
index 1d60a293e..c4b03dd1e 100644
--- a/tex/context/base/chem-str.mkiv
+++ b/tex/context/base/chem-str.mkiv
@@ -2,7 +2,7 @@
%D [ file=chem-ini,
%D version=2009.05.13,
%D subtitle=Chemistry,
-%D author=Hans Hagen,
+%D author=Hans Hagen \& Alan Braslau,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
@@ -10,8 +10,10 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This module in incomplete and experimental. Eventually this code
-%D will replace \PPCHTEX.
+%D The original \PPCHTEX\ code was written in pure \TEX\, although later we made
+%D the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between
+%D \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible
+%D but better implementation, later versions might provide more,
\writestatus{loading}{ConTeXt Chemistry Macros / Structure}
@@ -26,24 +28,24 @@
% Here we use chemicalformula instead, so no longer a mix:
%
% \startchemicalformula
-% \chemical{H_2}{top}{bottom}
+% \chemical{2H_2}{top}{bottom}
% \chemical{PLUS}{top}{bottom}
-% \chemical{O}{top}{bottom}
+% \chemical{O_2}{top}{bottom}
% \chemical{GIVES}{top}{bottom}
-% \chemical{H_2O}{top}{bottom}
+% \chemical{2H_2O}{top}{bottom}
% \stopchemicalformula
%
% \startchemicalformula
-% \chemical{H_2}
+% \chemical{2H_2}
% \chemical{PLUS}
-% \chemical{O}
+% \chemical{O_2}
% \chemical{GIVES}
-% \chemical{H_2O}
+% \chemical{2H_2O}
% \stopchemicalformula
%
% The inline variant has only one argument:
%
-% \chemical{H_2,PLUS,O,GIVES,H_2O}
+% \chemical{2H_2,PLUS,O_2,GIVES,2H_2O}
% todo: seven | eight | frontsix | fontfive | carbon | newmans | chair
@@ -58,11 +60,17 @@
\let\setupchemicals\setupchemical
-\unexpanded\def\setupchemicalframed
- {\dosingleempty\dosetupchemicalframed}
+%D We use a dedicated framed macro instead of inheriting one. This is both
+%D a historical and practical reason (like shared keys with different meaning
+%D that could clash, e.g.\ align).
+
+\defineframed
+ [\??chemicalframed]
+ [\c!align=\v!normal,
+ \c!strut=\v!no]
-\def\dosetupchemicalframed
- {\getparameters[\??chemicalframed]}
+\unexpanded\def\setupchemicalframed
+ {\setupframed[\??chemicalframed]}
\unexpanded\def\definechemical % is global (so we don't use the commandhandler)
{\dosingleargument\chem_define}
@@ -71,7 +79,7 @@
{\startnointerference
\edef\currentdefinedchemical{#1}%
\let\chemical\chem_chemical_nested
- \ctxlua{chemicals.undefine("#1")}%
+ \ctxcommand{undefinechemical("#1")}%
#2% flush
\stopnointerference}
@@ -79,7 +87,7 @@
{\dodoubleempty\chem_chemical_nested_indeed}
\def\chem_chemical_nested_indeed[#1][#2]%
- {\ctxlua{chemicals.define("\currentdefinedchemical",\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es)}}
+ {\ctxcommand{definechemical("\currentdefinedchemical",\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es)}}
% chemical symbols
@@ -90,20 +98,15 @@
{\setvalue{\??chemicalsymbol#1}{#2}}
\unexpanded\def\chemicalsymbol[#1]%
- {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname\s!unknown\else#1\fi\endcsname}
+ {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname#1\else\s!unknown\fi\endcsname}
-\definechemicalsymbol[\s!unknown][] % empty
+\definechemicalsymbol[\s!unknown][] % \char"FFFD empty
% size (small medium big)
\edef\chemicaltoplocation{t}
\edef\chemicalbotlocation{b}
-% \unexpanded\def\chemicaltext#1% in ppchtex we had a more clever alignment
-% {\usechemicalstyleandcolor\c!style\c!color
-% \strut
-% #1} % maybe also \setstrut
-
\unexpanded\def\chemicaltext#1%
{\mathematics
{\usechemicalstyleandcolor\c!style\c!color
@@ -147,7 +150,7 @@
\fi\fi
\the\everystructurechemical
\setbox\b_chem_result\hbox\bgroup
- \ctxlua{chemicals.start {
+ \ctxcommand{startchemical {
width = "\chemicalparameter\c!width",
height = "\chemicalparameter\c!height",
left = \chemicalparameter\c!left,
@@ -162,7 +165,7 @@
\unexpanded\def\stopchemical
{\stopnointerference
- \ctxlua{chemicals.stop()}%
+ \ctxcommand{stopchemical()}%
\egroup
\d_chem_width \wd\b_chem_result
\d_chem_height\ht\b_chem_result
@@ -171,15 +174,16 @@
\doifelsenothing{\chemicalparameter\c!frame}\chem_framed_nop\chem_framed_yes
\egroup}
-\def\chem_framed_yes
- {\localframed%
+\unexpanded\def\chem_framed_yes
+ {\localframedwithsettings
[\??chemicalframed]%
- [\c!frame=\chemicalparameter\c!frame,\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\b_chem_result\vss}}} % remove depth
+ [\c!frame=\chemicalparameter\c!frame]%
+ {\vbox{\box\b_chem_result\vss}}} % remove depth
-\def\chem_framed_nop
- {\localframed%
+\unexpanded\def\chem_framed_nop
+ {\directlocalframed
[\??chemicalframed]%
- [\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\b_chem_result\vss}}} % remove depth
+ {\vbox{\box\b_chem_result\vss}}} % remove depth
\let\startstructurechemical\startchemical
\let\stopstructurechemical \stopchemical
@@ -200,14 +204,14 @@
\def\strc_chem_indeed_three[#1][#2][#3]%
{\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored
- \ctxlua{chemicals.component(\!!bs#2\!!es, \!!bs\detokenize{#3}\!!es, { % maybe also pass first two args this way
+ \ctxcommand{chemicalcomponent(\!!bs#2\!!es, \!!bs\detokenize{#3}\!!es, { % maybe also pass first two args this way
rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax", % todo: scaled points
rulecolor = "\MPcolor{\chemicalparameter\c!rulecolor}" % we can precalculate this for speedup
} ) }%
\ignorespaces}
\def\strc_chem_indeed_two[#1][#2]%
- {\ctxlua{chemicals.component(\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es, { % maybe also pass first two args this way
+ {\ctxcommand{chemicalcomponent(\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es, { % maybe also pass first two args this way
rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax", % todo: scaled points
rulecolor = "\MPcolor{\chemicalparameter\c!rulecolor}" % we can precalculate this for speedup
} ) }%
@@ -289,8 +293,8 @@
\def\chem_arrow_construct#1#2#3%
{\enspace
\mathematics{#1%
- {\strut\hbox \!!spread 2\emwidth{\hss\ctxlua{chemicals.inline(\!!bs#2\!!es)}\hss}}% {\strut\hbox \!!spread 2em{\hss#2\hss}}%
- {\strut\hbox \!!spread 2\emwidth{\hss\ctxlua{chemicals.inline(\!!bs#3\!!es)}\hss}}}% {\strut\hbox \!!spread 2em{\hss#3\hss}}}%
+ {\strut\hbox \s!spread 2\emwidth{\hss\ctxcommand{inlinechemical(\!!bs#3\!!es)}\hss}}% {\strut\hbox \s!spread 2em{\hss#3\hss}}}%
+ {\strut\hbox \s!spread 2\emwidth{\hss\ctxcommand{inlinechemical(\!!bs#2\!!es)}\hss}}}% {\strut\hbox \s!spread 2em{\hss#2\hss}}%
\enspace}
% special macros (probably needs some more work)
@@ -428,9 +432,9 @@
\usechemicalstyleandcolor\c!style\c!color
\ifthirdargument
\ifsecondargument
- \halign{&\hss##\hss\cr#2\cr\molecule{#1}\cr#3\cr}%
+ \halign{\aligntab\hss\alignmark\alignmark\hss\cr#2\cr\molecule{#1}\cr#3\cr}%
\else
- \halign{&\hss##\hss\cr\molecule{#1}\cr#2\cr}%
+ \halign{\aligntab\hss\alignmark\alignmark\hss \cr\molecule{#1}\cr#2\cr}%
\fi
\else
\hbox{\molecule{#1}}%
@@ -440,30 +444,30 @@
\unexpanded\def\inlinechemical#1%
{\dontleavehmode
- \hbox{\usechemicalstyleandcolor\c!style\c!color\ctxlua{chemicals.inline(\!!bs#1\!!es)}}}
+ \hbox{\usechemicalstyleandcolor\c!style\c!color\ctxcommand{inlinechemical(\!!bs#1\!!es)}}}
\unexpanded\def\chemicalbondrule
- {\hbox{\vrule\!!height.75ex\!!depth-\dimexpr.75ex-\linewidth\relax\!!width1em\relax}}
+ {\hbox{\vrule\s!height.75\exheight\s!depth-\dimexpr.75\exheight-\linewidth\relax\s!width\emwidth\relax}}
\definechemicalsymbol[i:space] [\enspace\quad\enspace]
\definechemicalsymbol[i:plus] [\enspace\mathematics{+}\enspace]
\definechemicalsymbol[i:minus] [\enspace\mathematics{-}\enspace]
\definechemicalsymbol[i:gives] [\enspace\mathematics{\xrightarrow{}{}}\enspace]
-\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightpverleftarrow{}{}}\enspace]
+\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightoverleftarrow{}{}}\enspace]
\definechemicalsymbol[i:mesomeric] [\enspace\mathematics{\xleftrightarrow{}{}}\enspace]
\definechemicalsymbol[i:single] [\chemicalbondrule]
-\definechemicalsymbol[i:tripple] [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
-\definechemicalsymbol[i:double] [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:double] [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:triple] [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
\unexpanded\def\chemicalsinglebond {\chemicalsymbol[i:single]}
-\unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:tripple]}
-\unexpanded\def\chemicaltriplebond {\chemicalsymbol[i:double]}
+\unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:double]}
+\unexpanded\def\chemicaltriplebond {\chemicalsymbol[i:triple]}
\unexpanded\def\chemicalgives {\chemicalsymbol[i:gives]}
\unexpanded\def\chemicalmesomeric {\chemicalsymbol[i:mesomeric]}
\unexpanded\def\chemicalequilibrium{\chemicalsymbol[i:equilibrium]}
-\unexpanded\def\chemicalsplus {\chemicalsymbol[i:plus]}
-\unexpanded\def\chemicalsminus {\chemicalsymbol[i:minus]}
-\unexpanded\def\chemicalsspace {\chemicalsymbol[i:space]}
+\unexpanded\def\chemicalplus {\chemicalsymbol[i:plus]}
+\unexpanded\def\chemicalminus {\chemicalsymbol[i:minus]}
+\unexpanded\def\chemicalspace {\chemicalsymbol[i:space]}
\unexpanded\def\chemicalinline #1{#1}
% display
@@ -491,61 +495,133 @@
\setfalse\c_chem_has_bot}
\unexpanded\def\stopchemicalformula
- {\tabskip1em\relax
+ {\tabskip\emwidth\relax
\nointerlineskip
\ifconditional\c_chem_has_top
\ifconditional\c_chem_has_bot
- \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
\else
- \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr}%
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr}%
\fi
\else
\ifconditional\c_chem_has_bot
- \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
\else
- \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_mid\cr}%
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr}%
\fi
\fi
\egroup}
+% for the moment we have a special set
+
+\definechemicalsymbol[d:space] [\enspace\quad\enspace]
+\definechemicalsymbol[d:plus] [\enspace+\enspace]
+\definechemicalsymbol[d:minus] [\enspace-\enspace]
+\definechemicalsymbol[d:gives] [\rightarrowfill] % \chem_arrow_construct\xrightarrow
+\definechemicalsymbol[d:equilibrium] [\rightoverleftarrowfill] % \chem_arrow_construct\xrightoverleftarrow
+\definechemicalsymbol[d:mesomeric] [\leftarrowfill] % \chem_arrow_construct\xleftrightarrow
+\definechemicalsymbol[d:opencomplex] [\mathematics{\Bigg[}] % not yet ok
+\definechemicalsymbol[d:closecomplex][\mathematics{\Bigg]}] % not yet ok
+
+\definechemicalsymbol[d:SPACE] [{\chemicalsymbol[d:space]}]
+\definechemicalsymbol[d:PLUS] [{\chemicalsymbol[d:plus]}]
+\definechemicalsymbol[d:MINUS] [{\chemicalsymbol[d:minus]}]
+\definechemicalsymbol[d:GIVES] [{\chemicalsymbol[d:gives]}]
+\definechemicalsymbol[d:EQUILIBRIUM] [{\chemicalsymbol[d:equilibrium]}]
+\definechemicalsymbol[d:MESOMERIC] [{\chemicalsymbol[d:mesomeric]}]
+\definechemicalsymbol[d:OPENCOMPLEX] [{\chemicalsymbol[d:opencomplex]}]
+\definechemicalsymbol[d:CLOSECOMPLEX][{\chemicalsymbol[d:closecomplex]}]
+
\unexpanded\def\formulachemical
{\relax\dotriplegroupempty\chem_formula}
+% \def\chem_formula#1#2#3% we could do hboxes and measure
+% {\ifcsname\??chemicalsymbol\detokenize{#1}\endcsname
+% \t_chem_mid\expandafter{\the\t_chem_mid\chem_formula_mid{#1}{#2}{#3}}%
+% \else
+% \ifthirdargument
+% \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}%
+% \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}%
+% \else\ifsecondargument
+% \chem_formula_top_nop
+% \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}%
+% \else
+% \chem_formula_top_nop
+% \chem_formula_bot_nop
+% \fi\fi
+% \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}\aligntab}%
+% \fi}
+
\def\chem_formula#1#2#3% we could do hboxes and measure
- {\ifcsname\??chemicalsymbol\detokenize{#1}\endcsname
- \t_chem_mid\expandafter{\the\t_chem_mid\chem_formula_mid{#1}{#2}{#3}}%
+ {\ifthirdargument
+ \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}%
+ \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}%
+ \else\ifsecondargument
+ \chem_formula_top_nop
+ \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}%
\else
- \ifthirdargument
- \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}%
- \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}%
- \else\ifsecondargument
- \chem_formula_top_nop
- \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}%
- \else
- \chem_formula_top_nop
- \chem_formula_bot_nop
- \fi\fi
- \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}&}%
+ \chem_formula_top_nop
+ \chem_formula_bot_nop
+ \fi\fi
+ \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname
+ \t_chem_mid\expandafter{\the\t_chem_mid\chemicalsymbol[d:#1]\aligntab}%
+ \else
+ \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}\aligntab}%
\fi}
\def\chem_formula_mid#1%
{\csname\??chemicalsymbol\detokenize{#1}\endcsname}
-\def\chem_formula_top_nop {\t_chem_top\expandafter{\the\t_chem_top&}}
-\def\chem_formula_bot_nop {\t_chem_bot\expandafter{\the\t_chem_bot&}}
-\def\chem_formula_top_yes#1{\t_chem_top\expandafter{\the\t_chem_top\chem_formula_top_indeed{#1}&}\settrue\c_chem_has_top}
-\def\chem_formula_bot_yes#1{\t_chem_bot\expandafter{\the\t_chem_bot\chem_formula_bot_indeed{#1}&}\settrue\c_chem_has_bot}
+\def\chem_formula_top_nop {\t_chem_top\expandafter{\the\t_chem_top\aligntab}}
+\def\chem_formula_bot_nop {\t_chem_bot\expandafter{\the\t_chem_bot\aligntab}}
+\def\chem_formula_top_yes#1{\t_chem_top\expandafter{\the\t_chem_top\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top}
+\def\chem_formula_bot_yes#1{\t_chem_bot\expandafter{\the\t_chem_bot\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot}
\def\chem_formula_top_indeed#1{\strut#1}
\def\chem_formula_bot_indeed#1{\strut#1}
+% Experimental: defaults might change.
+
+\definefloat
+ [\v!chemical]
+ [\v!chemicals]
+
+\setuplabeltext
+ [\v!chemical=]
+
+\setupfloat
+ [\v!chemical]
+ [\c!location=\v!here,
+ \c!inner=\hsize.8\textwidth\dontleavehmode, % brr
+ \c!align={\v!flushleft,\v!lohi}]
+
+\setupcaption
+ [\v!chemical]
+ [\c!location=\v!right,
+ \c!distance=\zeropoint,
+ \c!width=.2\textwidth,
+ \c!align=\v!flushright]
+
+% Can be used as for displayed math: \startplaceformula... to display a chemical formula
+% or a chemical structure:
+%
+% \startplacechemical
+% \startchemicalformula
+% \chemical{2H_2}
+% \chemical{PLUS}
+% \chemical{O_2}
+% \chemical{GIVES}
+% \chemical{2H_2O}
+% \stopchemicalformula
+% \stopplacechemical
+
% gone: state option resolution offset (now frame offset) alternative
\setupchemicalframed
[\c!align=\v!normal,
\c!strut=\v!no,
\c!offset=\v!overlay,
- \c!frame=off]
+ \c!frame=\v!off]
\setupchemical
[\c!frame=,
diff --git a/tex/context/base/cldf-bas.lua b/tex/context/base/cldf-bas.lua
index 30a9265bc..9cf8dcd4a 100644
--- a/tex/context/base/cldf-bas.lua
+++ b/tex/context/base/cldf-bas.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['cldf-ini'] = {
+if not modules then modules = { } end modules ['cldf-bas'] = {
version = 1.001,
comment = "companion to cldf-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -22,6 +22,8 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
-- flush(ctxcatcodes,"}")
-- end
+-- maybe use context.generics
+
local type = type
local format = string.format
local utfchar = utf.char
@@ -32,13 +34,16 @@ local generics = context.generics
local variables = interfaces.variables
local new_rule = nodes.pool.rule
+local texcount = tex.count
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]]))
+ local n = #k
+ if n == 1 then
+ context([[\char%s\relax]],k[1])
+ elseif n > 0 then
+ context([[\char%s\relax]],concat(k,[[\relax\char]]))
+ end
elseif k then
context([[\char%s\relax]],k)
end
@@ -98,22 +103,22 @@ context.vrule = context.hrule
-- 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.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)
+ context([[\setbox%s\hbox{]],n)
else
- context("\\setbox\\%s\\hbox\\bgroup",n)
+ context([[\setbox\%s\hbox{]],n)
end
end
function context.startvboxregister(n)
if type(n) == "number" then
- context("\\setbox%s\\vbox\\bgroup",n)
+ context([[\setbox%s\vbox{]],n)
else
- context("\\setbox\\%s\\vbox\\bgroup",n)
+ context([[\setbox\%s\vbox{]],n)
end
end
@@ -122,19 +127,36 @@ context.stopvboxregister = context.egroup
function context.flushboxregister(n)
if type(n) == "number" then
- context("\\box%s ",n)
+ context([[\box%s ]],n)
else
- context("\\box\\%s",n)
+ context([[\box\%s]],n)
end
end
function context.beginvbox()
- context("\\vbox\\bgroup") -- we can do \bvbox ... \evbox (less tokens)
+ context([[\vbox{]]) -- we can do \bvbox ... \evbox (less tokens)
end
function context.beginhbox()
- context("\\hbox\\bgroup") -- todo: use fast one
+ context([[\hbox{]]) -- todo: use fast one
end
context.endvbox = context.egroup
context.endhbox = context.egroup
+
+local function allocate(name,what,cmd)
+ local a = format("c_syst_last_allocated_%s",what)
+ local n = texcount[a] + 1
+ if n <= texcount.c_syst_max_allocated_register then
+ texcount[a] = n
+ end
+ context("\\global\\expandafter\\%sdef\\csname %s\\endcsname %s\\relax",cmd or what,name,n)
+ return n
+end
+
+function context.newdimen (name) return allocate(name,"dimen") end
+function context.newskip (name) return allocate(name,"skip") end
+function context.newcount (name) return allocate(name,"count") end
+function context.newmuskip(name) return allocate(name,"muskip") end
+function context.newtoks (name) return allocate(name,"toks") end
+function context.newbox (name) return allocate(name,"box","mathchar") end
diff --git a/tex/context/base/cldf-com.lua b/tex/context/base/cldf-com.lua
index bacbbeafd..d9062594e 100644
--- a/tex/context/base/cldf-com.lua
+++ b/tex/context/base/cldf-com.lua
@@ -11,8 +11,8 @@ local context = context
local generics = context.generics -- needs documentation
local variables = interfaces.variables
-generics.starttabulate = "start" .. variables.tabulate -- todo: e!start
-generics.stoptabulate = "stop" .. variables.tabulate -- todo: e!stop
+generics.starttabulate = "starttabulate" -- "start" .. variables.tabulate -- todo: e!start
+generics.stoptabulate = "stoptabulate" -- "stop" .. variables.tabulate -- todo: e!stop
local NC, NR = context.NC, context.NR
diff --git a/tex/context/base/cldf-ini.lua b/tex/context/base/cldf-ini.lua
index ed86c2923..ad5f14855 100644
--- a/tex/context/base/cldf-ini.lua
+++ b/tex/context/base/cldf-ini.lua
@@ -25,7 +25,7 @@ local tex = tex
context = context or { }
local context = context
-local format, find, gmatch, gsub = string.format, string.find, string.gmatch, string.gsub
+local format, find, gmatch, gsub, validstring = string.format, string.find, string.gmatch, string.gsub, string.valid
local next, type, tostring, tonumber, setmetatable = next, type, tostring, tonumber, setmetatable
local insert, remove, concat = table.insert, table.remove, table.concat
local lpegmatch, lpegC, lpegS, lpegP, lpegCc = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.Cc
@@ -40,12 +40,14 @@ local isnode = node.is_node -- after 0.65 just node.type
local writenode = node.write
local copynodelist = node.copy_list
-local ctxcatcodes = tex.ctxcatcodes
-local prtcatcodes = tex.prtcatcodes
-local texcatcodes = tex.texcatcodes
-local txtcatcodes = tex.txtcatcodes
-local vrbcatcodes = tex.vrbcatcodes
-local xmlcatcodes = tex.xmlcatcodes
+local catcodenumbers = catcodes.numbers
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local prtcatcodes = catcodenumbers.prtcatcodes
+local texcatcodes = catcodenumbers.texcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+local vrbcatcodes = catcodenumbers.vrbcatcodes
+local xmlcatcodes = catcodenumbers.xmlcatcodes
local flush = texsprint
local flushdirect = texprint
@@ -344,9 +346,9 @@ end
local methodhandler = resolvers.methodhandler
-function context.viafile(data)
+function context.viafile(data,tag)
if data and data ~= "" then
- local filename = resolvers.savers.byscheme("virtual","viafile",data)
+ local filename = resolvers.savers.byscheme("virtual",validstring(tag,"viafile"),data)
-- context.startregime { "utf" }
context.input(filename)
-- context.stopregime()
@@ -410,7 +412,11 @@ local function writer(parent,command,first,...) -- already optimized before call
done = true
end
end
- flush(currentcatcodes,"]")
+ if done then
+ flush(currentcatcodes,"]")
+ else
+ flush(currentcatcodes,"[]")
+ end
elseif tn == 1 then -- some 20% faster than the next loop
local tj = ti[1]
if type(tj) == "function" then
diff --git a/tex/context/base/cldf-int.lua b/tex/context/base/cldf-int.lua
index 55db9fa0b..6cbfd666f 100644
--- a/tex/context/base/cldf-int.lua
+++ b/tex/context/base/cldf-int.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['mult-clm'] = {
+if not modules then modules = { } end modules ['cldf-int'] = {
version = 1.001,
comment = "companion to mult-clm.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -14,9 +14,12 @@ if not modules then modules = { } end modules ['mult-clm'] = {
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 catcodenumbers = catcodes.numbers
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local vrbcatcodes = catcodenumbers.vrbcatcodes
+
+local contextsprint = context.sprint
local trace_define = false trackers.register("context.define", function(v) trace_define = v end)
diff --git a/tex/context/base/cldf-ver.lua b/tex/context/base/cldf-ver.lua
index 237078157..b48fd253a 100644
--- a/tex/context/base/cldf-ver.lua
+++ b/tex/context/base/cldf-ver.lua
@@ -6,6 +6,10 @@ if not modules then modules = { } end modules ['cldf-ver'] = {
license = "see context related readme files"
}
+-- We have better verbatim: context.verbatim so that needs to be looked
+-- into. We can also directly store in buffers although this variant works
+-- better when used mixed with other code (synchronization issue).
+
local concat, tohandle = table.concat, table.tohandle
local find, splitlines = string.find, string.splitlines
local tostring, type = tostring, type
@@ -41,7 +45,7 @@ table .tocontext = t_tocontext
string .tocontext = s_tocontext
boolean.tocontext = b_tocontext
-function tocontext(first,...)
+function context.tocontext(first,...)
local t = type(first)
if t == "string" then
s_tocontext(first,...)
diff --git a/tex/context/base/colo-ext.mkiv b/tex/context/base/colo-ext.mkiv
index af6c3830e..8878da485 100644
--- a/tex/context/base/colo-ext.mkiv
+++ b/tex/context/base/colo-ext.mkiv
@@ -29,18 +29,10 @@
%D
%D will negate the colors in box zero.
-% \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
{\startnegative % might change
-% \startcolor[\s!white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor
+ % \startcolor[\s!white]\vrule\s!height\ht#1\s!depth\dp#1\s!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%
diff --git a/tex/context/base/colo-icc.lua b/tex/context/base/colo-icc.lua
index 904d42143..4ab28eb68 100644
--- a/tex/context/base/colo-icc.lua
+++ b/tex/context/base/colo-icc.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['colo-ini'] = {
+if not modules then modules = { } end modules ['colo-icc'] = {
version = 1.000,
comment = "companion to colo-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/tex/context/base/colo-ini.lua b/tex/context/base/colo-ini.lua
index 747e2116f..e08f3d387 100644
--- a/tex/context/base/colo-ini.lua
+++ b/tex/context/base/colo-ini.lua
@@ -16,7 +16,8 @@ local trace_define = false trackers.register("colors.define",function(v) trace_
local report_colors = logs.reporter("colors","defining")
-local attributes, context, commands = attributes, context, commands
+local attributes, backends, storage = attributes, backends, storage
+local context, commands = context, commands
local settings_to_hash_strict = utilities.parsers.settings_to_hash_strict
@@ -666,83 +667,51 @@ function colors.defineintermediatecolor(name,fraction,c_one,c_two,a_one,a_two,sp
end
end
---~ local function f(one,two,i,fraction_one,fraction_two)
---~ local otf = fraction_one * one[i] + fraction_two * two[i]
---~ if otf > 1 then
---~ otf = 1
---~ end
---~ return otf
---~ end
-
---~ function colors.defineduocolor(name,fraction_one,c_one,fraction_two,c_two,global,freeze)
---~ 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
---~ local csone, cstwo = one[1], two[1]
---~ local ca
---~ if csone == 2 then
---~ ca = register_color(name,'gray',f(one,two,2,fraction_one,fraction_two))
---~ elseif csone == 3 then
---~ ca = register_color(name,'rgb', f(one,two,3,fraction_one,fraction_two),
---~ f(one,two,4,fraction_one,fraction_two),
---~ f(one,two,5,fraction_one,fraction_two))
---~ elseif csone == 4 then
---~ ca = register_color(name,'cmyk',f(one,two,6,fraction_one,fraction_two),
---~ f(one,two,7,fraction_one,fraction_two),
---~ f(one,two,8,fraction_one,fraction_two),
---~ f(one,two,9,fraction_one,fraction_two))
---~ else
---~ ca = register_color(name,'gray',f(one,two,2,fraction_one,fraction_two))
---~ end
---~ definecolor(name,ca,global,freeze)
---~ end
---~ end
-
- local function f(i,colors,fraction)
- local otf = 0
- for c=1,#colors do
- otf = otf + (tonumber(fraction[c]) or 1) * colors[c][i]
- end
- if otf > 1 then
- otf = 1
- end
- return otf
+local function f(i,colors,fraction)
+ local otf = 0
+ for c=1,#colors do
+ otf = otf + (tonumber(fraction[c]) or 1) * colors[c][i]
+ end
+ if otf > 1 then
+ otf = 1
end
+ return otf
+end
- function colors.definemixcolor(name,fractions,cs,global,freeze)
- local values = { }
- for i=1,#cs do -- do fraction in here
- local v = colorvalues[cs[i]]
- if not v then
- return
- end
- values[i] = v
- end
- local csone = values[1][1]
- local ca
- if csone == 2 then
- ca = register_color(name,'gray',f(2,values,fractions))
- elseif csone == 3 then
- ca = register_color(name,'rgb', f(3,values,fractions),
- f(4,values,fractions),
- f(5,values,fractions))
- elseif csone == 4 then
- ca = register_color(name,'cmyk',f(6,values,fractions),
- f(7,values,fractions),
- f(8,values,fractions),
- f(9,values,fractions))
- else
- ca = register_color(name,'gray',f(2,values,fractions))
+function colors.definemixcolor(name,fractions,cs,global,freeze)
+ local values = { }
+ for i=1,#cs do -- do fraction in here
+ local v = colorvalues[cs[i]]
+ if not v then
+ return
end
- definecolor(name,ca,global,freeze)
+ values[i] = v
end
+ local csone = values[1][1]
+ local ca
+ if csone == 2 then
+ ca = register_color(name,'gray',f(2,values,fractions))
+ elseif csone == 3 then
+ ca = register_color(name,'rgb', f(3,values,fractions),
+ f(4,values,fractions),
+ f(5,values,fractions))
+ elseif csone == 4 then
+ ca = register_color(name,'cmyk',f(6,values,fractions),
+ f(7,values,fractions),
+ f(8,values,fractions),
+ f(9,values,fractions))
+ else
+ ca = register_color(name,'gray',f(2,values,fractions))
+ end
+ definecolor(name,ca,global,freeze)
+end
-- for the moment downward compatible
local patterns = { "colo-imp-%s.mkiv", "colo-imp-%s.tex", "colo-%s.mkiv", "colo-%s.tex" }
local function action(name,foundname)
+ -- could be one command
context.startreadingfile()
context.startcolorset { name }
context.input(foundname)
@@ -877,3 +846,22 @@ end
-- context.popcatcodes()
-- end
+-- handy
+
+local models = storage.allocate { "all", "gray", "rgb", "cmyk", "spot" }
+
+colors.models = models -- check for usage elsewhere
+
+function colors.spec(name)
+ local l = attributes_list[a_color]
+ local t = colorvalues[l[name]] or colorvalues[l.black]
+ return {
+ model = models[t[1]] or models[1],
+ s = t[2],
+ r = t[3], g = t[4], b = t[5],
+ c = t[6], m = t[7], y = t[8], k = t[9],
+ }
+end
+
+-- inspect(attributes.colors.spec("red"))
+-- inspect(attributes.colors.spec("red socks"))
diff --git a/tex/context/base/colo-ini.mkiv b/tex/context/base/colo-ini.mkiv
index 5721bb513..629f2b96a 100644
--- a/tex/context/base/colo-ini.mkiv
+++ b/tex/context/base/colo-ini.mkiv
@@ -242,8 +242,8 @@
\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
+ \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors{10}\v!rgb \fi
+ \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors{10}\v!cmyk\fi
\colo_helpers_set_current_model
\ifproductionrun
\edef\p_pagecolormodel{\directcolorsparameter\c!pagecolormodel}%
@@ -357,16 +357,26 @@
\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_one#1#2% get rid of { } in #2
+% {\colo_palets_define_two{#1}[#2]}%
+
+\def\colo_palets_define_one#1#2% get rid of { }
+ {\doifassignmentelse{#2} % catch empty entries
+ {\colo_palets_define_two{#1}[#2]}
+ {\colo_palets_define_three{#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}}%
+\def\colo_palets_define_three#1#2%
+ {\ifcsname\??colorpaletspecification#2\endcsname
+ \processcommacommand[\csname\??colorpaletspecification#2\endcsname]{\colo_palets_define_one{#1}}%
+ \fi}
+
\let\paletsize\!!zerocount
-\def\getpaletsize[#1]%
+\unexpanded\def\getpaletsize[#1]% only works for valid k=v definitions
{\getcommacommandsize[\csname\??colorpaletspecification#1\endcsname]%
\edef\paletsize{\number\commalistsize}}
@@ -802,9 +812,19 @@
\def\defaulttextcolor {black}
\def\s!themaintextcolor{themaintextcolor}
+\unexpanded\def\inheritmaintextcolor
+ {\ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi}
+
+\unexpanded\def\onlyinheritmaintextcolor
+ {\ifx\maintextcolor\empty
+ \deactivatecolor
+ \else
+ \colo_helpers_activate\maintextcolor
+ \fi}
+
\appendtoks
\deactivatecolor % public?
- \ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi
+ \inheritmaintextcolor
\to \everybeforeoutput
\def\colo_helpers_switch_to_maintextcolor#1%
@@ -961,7 +981,7 @@
% ignores in attribute handler
%
-% \def\forcecolorhack{\vrule\!!width\zeropoint\!!height\zeropoint\!!depth\zeropoint}
+% \def\forcecolorhack{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
% \normal added else fails in metafun manual (leaders do a hard scan)
diff --git a/tex/context/base/colo-run.lua b/tex/context/base/colo-run.lua
index 4f1916d5a..27f7c6b12 100644
--- a/tex/context/base/colo-run.lua
+++ b/tex/context/base/colo-run.lua
@@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['colo-run'] = {
license = "see context related readme files"
}
--- For historic reasons the core has a couple of tracing
--- features. Nowadays these would end up in modules.
+-- For historic reasons the core has a couple of tracing features. Nowadays
+-- these would end up in modules.
+
+local colors, commands, context, utilities = colors, commands, context, utilities
local colors= attributes.colors
diff --git a/tex/context/base/colo-run.mkiv b/tex/context/base/colo-run.mkiv
index c330accf3..5084fdd35 100644
--- a/tex/context/base/colo-run.mkiv
+++ b/tex/context/base/colo-run.mkiv
@@ -42,9 +42,9 @@
%D Palets
\unexpanded\gdef\showpalet
- {\dodoubleargument\doshowpalet}
+ {\dodoubleargument\colo_show_palet}
-\gdef\doshowpalet[#1][#2]%
+\gdef\colo_show_palet[#1][#2]%
{\ifcsname\??colorpalet#1\endcsname
\doifinsetelse\v!vertical{#2} \colo_palets_show_vertical \colo_palets_show_horizontal [#1][#2]%
\fi}
@@ -59,8 +59,8 @@
\tabskip\zeropoint
\def\colo_palets_show_palet##1%
{\doifinsetelse\v!number{#2}{##1\hskip.5em}{}&
- \color[##1]{\vrule\!!width3em\!!height\strutht\!!depth\strutdp}%
- \graycolor[##1]{\vrule\!!width3em\!!height\strutht\!!depth\strutdp}&
+ \color[##1]{\vrule\s!width3em\s!height\strutht\s!depth\strutdp}%
+ \graycolor[##1]{\vrule\s!width3em\s!height\strutht\s!depth\strutdp}&
\doifinset\v!value{#2}{\hskip.5em\colorvalue{##1}}\crcr}
\halign
{\hss##&\hss##\hss&##\cr
@@ -92,11 +92,11 @@
\colo_palets_process[#1]\colo_palets_show_palet}\cr
\doifinset\v!name{#2}{#1\hskip.5em}%
\def\colo_palets_show_palet##1%
- {&\strut\color[##1]{\vrule\!!width\!!widtha\!!height\strutht\!!depth\zeropoint}}%
+ {&\strut\color[##1]{\vrule\s!width\!!widtha\s!height\strutht\s!depth\zeropoint}}%
\colo_palets_process[#1]\colo_palets_show_palet\crcr
\noalign{\vskip-\strutdepth}%
\def\colo_palets_show_palet##1%
- {&\graycolor[##1]{\vrule\!!width\!!widtha\!!height\zeropoint\!!depth\strutdp}}%
+ {&\graycolor[##1]{\vrule\s!width\!!widtha\s!height\zeropoint\s!depth\strutdp}}%
\colo_palets_process[#1]\colo_palets_show_palet\crcr
\doifinset\v!value{#2}
{\def\colo_palets_show_palet##1%
@@ -137,13 +137,13 @@
\def\colo_palets_compare##1%
{\hbox
{\setbox0\hbox
- {#1[##1]{\vrule\!!width\hsize\!!height3ex}}%
+ {#1[##1]{\vrule\s!width\hsize\s!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}}%
+ {\hss#1[####1]{\vrule\s!width.5\!!widtha\s!height2.25ex\s!depth-.75ex}\hss}}%
\processcommacommand[\getvalue{\??colorpalet#2}]\colo_palets_compare}}
\endgraf}
\processcommacommand[\getvalue{\??colorpalet#2}]\colo_palets_compare}}
@@ -171,8 +171,8 @@
{\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
+ \color[#1:##1]{\vrule\s!width4em\s!height\strutht\s!depth\zeropoint}\cr
+ \graycolor[#1:##1]{\vrule\s!width4em\s!height\zeropoint\s!depth\strutdp}\cr
\doifinset\v!value{#2}{\colorvalue{#1:##1}\strut}\crcr}}}}%
\hbox
{\doifinset\v!name{#2}
@@ -195,8 +195,8 @@
\def\colo_groups_show_group##1%
{\doifcolor{#1:##1}
{\doifinset\v!number{#2}{##1\hskip.5em}&
- \color[#1:##1]{\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}%
- \graycolor[#1:##1]{\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}&
+ \color[#1:##1]{\vrule\s!width2.5em\s!height\strutht\s!depth\strutdp}%
+ \graycolor[#1:##1]{\vrule\s!width2.5em\s!height\strutht\s!depth\strutdp}&
\doifinset\v!value{#2}{\hskip.5em\colorvalue{#1:##1}}\crcr}}%
\halign
{\hss##&\hss##\hss&##\hss\cr
@@ -228,11 +228,11 @@
\def\colo_groups_compare_step#1#2#3%
{\hbox to \hsize
{\setbox0\hbox
- {#1[#2:#3]{\vrule\!!width\hsize\!!height3ex}}%
+ {#1[#2:#3]{\vrule\s!width\hsize\s!height3ex}}%
\wd0\zeropoint
\box0
\hbox to \hsize
- {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}\hss}}}
+ {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\vrule\s!width.5\!!widtha\s!height2.25ex\s!depth-.75ex}\hss}}}
\endgraf}
\protect \endinput
diff --git a/tex/context/base/cont-log.mkiv b/tex/context/base/cont-log.mkiv
index 67647920d..5d4133143 100644
--- a/tex/context/base/cont-log.mkiv
+++ b/tex/context/base/cont-log.mkiv
@@ -118,7 +118,7 @@
\logofont}
\def\syst_logos_meta_hyphen % there is no hyphenchar in this font
- {\discretionary{\vrule\!!height.33em\!!depth-.27em\!!width.33em}{}{}}
+ {\discretionary{\vrule\s!height.33em\s!depth-.27em\s!width.33em}{}{}}
\unexpanded\def\MetaFont
{\dontleavehmode
@@ -270,4 +270,12 @@
\unexpanded\def\MPII{MpII}
\unexpanded\def\MPIV{MpIV}
+\appendtoks
+ \def\ConTeXt {ConTeXt}%
+ \def\MetaPost{MetaPost}%
+ \def\MetaFont{MetaFont}%
+ \def\MetaFun {MetaFun}%
+ \def\TeX {TeX}%
+\to \everysimplifycommands
+
\protect \endinput
diff --git a/tex/context/base/cont-new.mkii b/tex/context/base/cont-new.mkii
index b4958762f..2c07401d8 100644
--- a/tex/context/base/cont-new.mkii
+++ b/tex/context/base/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.05.30 11:26}
+\newcontextversion{2012.10.19 00:06}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index 5a28f8e29..e791d3ba8 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,515 +11,60 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.05.30 11:26}
+\newcontextversion{2012.10.19 00:06}
-%D This file is loaded at runtime, thereby providing an
-%D excellent place for hacks, patches, extensions and new
-%D features.
+%D This file is loaded at runtime, thereby providing an excellent place for
+%D hacks, patches, extensions and new features.
\unprotect
\writestatus\m!system{beware: some patches loaded from cont-new.mkiv}
-\def\dividedsize#1#2#3% size gap n
- {\dimexpr
- \ifnum\dimexpr#1\relax>\plusone
- (\dimexpr#1\relax-\numexpr#3-1\relax\dimexpr#2\relax)/#3\else#1%
- \fi
- \relax}
-
-\def\singlewidened #1{\hbox spread 1em{\hss#1\hss}}
-\def\complexwidened[#1]#2{\hbox spread #1{\hss#2\hss}}
+%D Maybe:
-\definecomplexorsimple\widened
-
-\let\active\activecatcode % for a while (tikz)
-
-% todo
-%
-% \def\definelocation{\dodoubleargument\dodefinelocation}
-% \def\dodefinelocation[#1][#2]{\setvalue{loc:#1}{#2}}
-%
-% \definelocation[lt] [\v!left\v!top]
-% \definelocation[tl] [\v!left\v!top]
-% \definelocation[\v!top\v!left][\v!left\v!top]
-%
-% \def\getlocation#1{\executeifdefined{loc:#1}{#1}}
-
-% \let\cs\getvalue % no, we want \cs to be czech
-
-% experimental so this may change
+\unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox}
+\unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop}
-\def\startdescriptions
- {\dosingleempty\dostartdescriptions}
+%D Needs some work:
-\def\dostartdescriptions[#1]%
- {\begingroup
- \def\item{\getvalue{#1}}%
- \let\dostoppairdescription \donothing
- \let\@@description \dostartpairdescription
- \let\@@startsomedescription\dostartsomedescription}
+\unexpanded\def\startgridcorrection
+ {\dosingleempty\spac_grid_correction_start}
-\def\stopdescriptions
- {\dostoppairdescription
- \endgroup}
-
-\def\dostartpairdescription[#1][#2]%
- {\dostoppairdescription
- \def\dostoppairdescription{\@@stopdescription{#1}}%
- \bgroup
- \def\currentdescription{#1}%
- \doifelse{\descriptionparameter{\s!do\c!state}}\v!start
- {\@@makedescription{#1}[#2]{}}
- {\@@makedescription{#1}[#2]}}
-
-\def\dostartsomedescription% #1[#2]#3%
- {\bgroup
- \@@makedescription} % {#1}[#2]{#3}}
-
-% \starttext
-%
-% \definedescription[test]
-%
-% \startdescriptions
-% \test{Foo} Bar bar bar
-% \test{Foo} Bar bar bar
-% \test{Foo} Bar bar bar
-% \stopdescriptions
-%
-% \startdescriptions[test]
-% \item{Foo} Bar bar bar
-% \item{Foo} Bar bar bar
-% \item{Foo} Bar bar bar
-% \stopdescriptions
-%
-% \startdescriptions
-% \starttest{Foo} Bar bar bar \stoptest
-% \starttest{Foo} Bar bar bar \stoptest
-% \starttest{Foo} Bar bar bar \stoptest
-% \stopdescriptions
-%
-% \startdescriptions[test]
-% \item{Foo} Bar bar bar
-% \item{Foo} Bar bar bar
-% \item{Foo} Bar bar bar
-% \stopdescriptions
-%
-% \stoptext
-
-% this will be activated when
-%
-% \newinsert\thispageinsert % <- installinsertion
-%
-% \def\flushatthispage
-% {\bgroup
-% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}%
-% \hbox}
-%
-% \appendtoks
-% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi
-% \to \everyshipout
-
-% \definemarkedpage[nobackgrounds]
-% \markpage[nobackgrounds]
-% \doifmarkedpageelse{nobackgrounds}
-
-% Just a simple and fast hanger, for usage in macros.
-
-\def\setuphanging
- {\dodoubleempty\getparameters[\??ha]}
-
-\setuphanging
- [\c!distance=.5em]
-
-\def\starthanging
- {\noindent\bgroup
- \dowithnextbox
- {\setbox\nextbox\hbox{\flushnextbox\hskip\@@hadistance}%
- \hangindent\nextboxwd
- \hangafter\plusone
- \flushnextbox\ignorespaces}
- \hbox}
-
-\def\stophanging
- {\endgraf
- \egroup}
-
-% experimental
-
-\def\stophangaround
- {\endgraf
- \egroup}
-
-\def\starthangaround
- {\noindent\bgroup
- \dowithnextbox
- {\ifdim\nextboxht>\strutht\setbox\nextbox\tbox{\flushnextbox}\fi
- \setbox\nextbox\hbox{\flushnextbox\hskip\@@hadistance}%
- \getboxheight\scratchdimen\of\box\nextbox
- \getnoflines\scratchdimen
- \nextboxht\strutht
- \nextboxdp\strutdp
- \hangindent\nextboxwd
- \hangafter-\noflines
- \llap{\flushnextbox}\ignorespaces}
- \hbox}
-
-\def\modevalue#1#2#3%
- {\@EA\ifx\csname\@mode@\systemmodeprefix#1\endcsname\endcsname\enabledmode#2\else#2\fi}
-
-\def\systemmodevalue#1%
- {\modevalue{\systemmodeprefix#1}}
-
-% new, still to be improved
-%
-% \dorecurse{10}
-% {\input thuan
-% \placefigure{}{\framed[height=1.5cm]{test}}
-% \placefloatplaceholder}
-
-\def\placefloatplaceholder
- {\ifroomforfloat \else
- \scratchdimen\pagegoal
- \advance\scratchdimen-\pagetotal
- \advance\scratchdimen-3\lineheight
- \ifdim\scratchdimen>\zeropoint
- \startlinecorrection[blank]
- \mhbox{\inframed{\labeltexts{placeholder}{\lastcaptiontag}}}%
- \stoplinecorrection
- \else
- \allowbreak
- \fi
- \fi}
-
-\setuplabeltext
- [placeholder={, moved}]
-
-% move to support module, and then use context(...)
-
-\startluacode
- function commands.percentageof(str,dim)
- local n = str:match("^(.*)%%$")
- context.sprint(tex.ctxcatcodes,(n and (tonumber(n)/100)*dim .. "sp") or str)
- end
-\stopluacode
-
-\gdef\setpercentdimen#1#2%
- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax}
-
-% \scratchdimen=100pt \setpercentdimen\scratchdimen{10\letterpercent} \the\scratchdimen
-% \scratchdimen=100pt \setpercentdimen\scratchdimen{5pt} \the\scratchdimen
-
-\bgroup \permitcircumflexescape
-
-\obeylines % don't remove %'s !
-
-\gdef\collapsedspace#1%
- {\ifx#1^^M%
- \expandafter\collapsedspace
- \else
- \space
- \expandafter#1%
- \fi}
-
-\gdef\collapsespaces
- {\prependtoksonce\relax\to\everyeof%
- \ignorelines%
- \ignoretabs%
- \let\obeyedspace\collapsedspace%
- \obeyspaces}
-
-\egroup
-
-\def\inlinedbox
- {\bgroup
- \dowithnextbox
- {\scratchdimen\nextboxht
- \advance\scratchdimen\nextboxdp
- \advance\scratchdimen-\lineheight
- \divide\scratchdimen\plustwo
- \advance\scratchdimen\strutdepth
- \setbox\nextbox\hbox{\lower\scratchdimen\flushnextbox}%
- \nextboxht\strutht
- \nextboxdp\strutdp
- \flushnextbox
- \egroup}%
- \hbox}
-
-\def\dimenratio#1#2% etex only
- {\withoutpt\the\dimexpr2\dimexpr(#1)/\dimexpr(#2)/32768\relax\relax}
-
-\def\doxprecurse#1#2%
- {\ifnum#1=\zerocount % no \ifcase
- \expandafter\gobblethreearguments
- \else
- #2\expandafter\expandafter\expandafter\doxprecurse\expandafter
- \fi\expandafter{\the\numexpr#1-1\relax}{#2}}
-
-\def\buttonframed{\dodoubleempty\localframed[\??bt]} % goodie
-
-\unexpanded\def\asciistr#1{\dontleavehmode{\defconvertedargument\ascii{#1}\verbatimfont\ascii}}
-
-\def\shapefill{\vskip\zeropoint\!!plus\lineheight\!!minus\lineheight\relax}
-
-% \ruledhbox
-% {\startignorespaces
-% \def\oeps{a}
-% \startignorespaces
-% \def\oeps{a}
-% \stopignorespaces
-% \def\oeps{a}
-% \stopignorespaces
-% \oeps}
-
-\newsignal\boissignal
-\newcount \boislevel
-
-\long\def\startignorespaces
- {\advance\boislevel\plusone
- \ifcase\boislevel\or \ifhmode
- \hskip\boissignal
- \fi \fi
- \ignorespaces}
-
-\long\def\stopignorespaces
- {\ifcase\boislevel\or \ifhmode
- \doloop
- {\ifdim\lastskip=\zeropoint
- \exitloop
- \else\ifdim\lastskip=\boissignal
- \unskip
- \exitloop
- \else
- \unskip
- \fi\fi}%
- \fi \fi
- \advance\boislevel\minusone}
-
-\def\minimalhbox#1#%
- {\dowithnextbox
- {\bgroup
- \setbox\scratchbox\hbox#1{\hss}%
- \ifdim\nextboxwd<\wd\scratchbox\nextboxwd\wd\scratchbox\fi
- \flushnextbox
- \egroup}
- \hbox}
-
-\def\gobbleuntilempty#1\empty{}
-
-\def\dodimchoice#1#2#3%
- {\ifdim#1#2%
- #3\@EA\gobbleuntilempty
- \else
- \@EA\dodimchoice
- \fi{#1}}
-
-\def\donumchoice#1#2#3%
- {\ifnum#1#2%
- #3\@EA\gobbleuntilempty
- \else
- \@EA\dodimchoice
- \fi{#1}}
-
-\def\dimchoice#1#2{\dodimchoice{#1}#2{=#1}{#1}\empty}
-\def\numchoice#1#2{\donumchoice{#1}#2{=#1}{#1}\empty}
-
-% \the\dimexpr(\dimchoice {7pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
-% \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\tabulaterule % to be redone, not correct
- {\dotabulaterule
- {\hrule\!!height.5\scratchdimen\!!depth.5\scratchdimen\relax
- \doifvalue{\??tt\currenttabulate\c!distance}\v!grid
- {\kern-\scratchdimen}}} % experimental tm-prikkels
-% so far
-
-% between alignment lines certain rules apply, and even a
-% simple test can mess up a table, which is why we have a
-% special test facility
-%
-% \ruledvbox
-% {\starttabulate[|l|p|]
-% \NC 1test \NC test \NC \NR
-% \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
-% \stoptabulate}
-
-\long\def\tableifelse#1%
- {\tablenoalign
- {#1%
- {\aftergroup \firstoftwoarguments}%
- {\aftergroup\secondoftwoarguments}}}
-
-\long \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
-
-\def\tightvbox{\dowithnextbox{\nextboxdp\zeropoint\flushnextbox}\vbox}
-\def\tightvtop{\dowithnextbox{\nextboxht\zeropoint\flushnextbox}\vtop}
-
-% what is this stupid macro meant for:
-
-\def\hyphenationpoint
- {\hskip\zeropoint}
-
-\def\hyphenated#1%
- {\bgroup
- \!!counta\zerocount
- \def\hyphenated##1{\advance\!!counta\plusone}%
- \handletokens#1\with\hyphenated
- \!!countb\plusone
- \def\hyphenated##1%
- {##1%
- \advance\!!countb\plusone\relax
- \ifnum\!!countb>2 \ifnum\!!countb<\!!counta
- \hyphenationpoint
- \fi\fi}%
- \handletokens#1\with\hyphenated
- \egroup}
-
-\def\obeysupersubletters
- {\let\super\normalsuper
- \let\suber\normalsuber
- \let\normalsuper\letterhat
- \let\normalsuber\letterunderscore
- \enablesupersub}
-
-\def\obeysupersubmath
- {\let\normalsuper\letterhat
- \let\normalsuber\letterunderscore
- \enablesupersub}
-
-\def\startgridcorrection
- {\dosingleempty\dostartgridcorrection}
-
-\def\dostartgridcorrection[#1]%
+\def\spac_grid_correction_start[#1]%
{\ifgridsnapping
\snaptogrid[#1]\vbox\bgroup
\else
\startbaselinecorrection
\fi}
-\def\stopgridcorrection
+\unexpanded\def\stopgridcorrection
{\ifgridsnapping
\egroup
\else
\stopbaselinecorrection
\fi}
-
-\def\checkgridsnapping
+
+\unexpanded\def\checkgridsnapping
{\lineskip\ifgridsnapping\zeropoint\else\normallineskip\fi}
-
-\def\startplaatsen
- {\dosingleempty\dostartplaatsen}
-\def\dostartplaatsen[#1]% tzt n*links etc
- {\endgraf
- \noindent\bgroup
- \setlocalhsize
- \hbox to \localhsize\bgroup
- \doifnot{#1}\v!left\hss
- \def\stopplaatsen
- {\unskip\unskip\unskip
- \doifnot{#1}\v!right\hss
- \egroup
- \egroup
- \endgraf}%
- \gobblespacetokens}
+%D Probably obsolete:
-% \startplaatsen[links] bla \stopplaatsen
-
-\def\startcolumnmakeup % don't change
+\unexpanded\def\startcolumnmakeup % don't change
{\bgroup
- \getrawnoflines\textheight % teksthoogte kan topskip hebben, dus raw
- \scratchdimen\noflines\lineheight
- \advance\scratchdimen-\lineheight
- \advance\scratchdimen\topskip
- \setbox\scratchbox
- \ifcase\showgridstate\vbox\else\ruledvbox\fi to \scratchdimen\bgroup
- \forgetall} % ! don't change
+ \getrawnoflines\textheight % raw as we cna have topskip
+ \setbox\scratchbox\vbox to \dimexpr\noflines\lineheight-\lineheight+\topskip\relax
+ \bgroup
+ \forgetall}
-\def\stopcolumnmakeup
+\unexpanded\def\stopcolumnmakeup
{\egroup
\dp\scratchbox\zeropoint
\wd\scratchbox\textwidth
\box\scratchbox
\egroup
\page_otr_command_synchronize_hsize}
-
-\long\def\startexternalfigure
- {\dotripleempty\dostartexternalfigure}
-
-\long\def\dostartexternalfigure[#1][#2][#3]#4\stopexternalfigure
- {\gdef\figuredescription{#4}%
- \externalfigure[#1][#2][#3]%
- \globallet\figuredescription\empty}
-
-\let\figuredescription\empty
-
-% incomplete, will be a special case of float placement
-
-\def\startfixed{\dosingleempty\dostartfixed}
-
-\def\dostartfixed[#1]%
- {\expanded{\dowithnextbox{\noexpand\dodofixed{\ifhmode0\else1\fi}{#1}}}%
- \vbox\bgroup
- \setlocalhsize}
-
-\def\stopfixed
- {\egroup}
-
-\def\dodofixed#1#2%
- {\ifcase#1\relax
- \processaction
- [#2]
- [ \v!high=>\bbox {\flushnextbox},
- \v!low=>\tbox {\flushnextbox},
- \v!middle=>\vcenter{\flushnextbox},
- \v!lohi=>\vcenter{\flushnextbox},
- \s!unknown=>\tbox {\flushnextbox},
- \s!default=>\tbox {\flushnextbox}]%
- \else
- \startbaselinecorrection
- \noindent\flushnextbox
- \stopbaselinecorrection
- \fi}
-
-% \startitemize
-%
-% \item \externalfigure[koe][height=2cm]
-% \item \externalfigure[koe][height=2cm]
-% \item \externalfigure[koe][height=2cm]
-% \item \externalfigure[koe][height=2cm]
-%
-% \page
-%
-% \item \startfixed \externalfigure[koe][height=2cm]\stopfixed
-% \item \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
-% \item \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
-% \item \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
-%
-% \page
-%
-% \item test \startfixed \externalfigure[koe][height=2cm]\stopfixed
-% \item test \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
-% \item test \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
-% \item test \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
-%
-% \page
-%
-% \item test \par \startfixed \externalfigure[koe][height=2cm]\stopfixed
-% \item test \par \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
-% \item test \par \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
-% \item test \par \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
-%
-% \stopitemize
-
-\def\obeyfollowingtoken{{}} % end \cs scanning
-
-% potential new defaults:
-%
-% \setbreakpoints[compound]
-% till we fixed all styles:
+%D Till we fixed all styles:
\let\\=\crlf
diff --git a/tex/context/base/cont-nop.mkiv b/tex/context/base/cont-nop.mkiv
new file mode 100644
index 000000000..c8188503e
--- /dev/null
+++ b/tex/context/base/cont-nop.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=cont-nop,
+%D version=2012.06.01,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=Startup Dummy,
+%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
+
+\writestatus\m!system{loading dummy replacement for jobname}
+
+\protect
+
+\finishjob
+
+\endinput
diff --git a/tex/context/base/cont-yes.mkiv b/tex/context/base/cont-yes.mkiv
new file mode 100644
index 000000000..2a032fc0b
--- /dev/null
+++ b/tex/context/base/cont-yes.mkiv
@@ -0,0 +1,80 @@
+%D \module
+%D [ file=cont-yes,
+%D version=2012.06.01,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=Startup Stub,
+%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.
+
+% At some point I will reconsider the \starttext .. \stoptext
+% wraping as we can assume proper styling. It's a left-over from
+% mkii that we need to get rid of.
+
+\startluacode
+
+ -- When a style is loaded there is a good change that we never enter
+ -- this code.
+
+ environment.initializefilenames()
+
+ local arguments = environment.arguments
+ local suffix = environment.suffix
+ local filename = environment.filename
+
+ if suffix == "xml" or arguments.forcexml then
+
+ -- Maybe we should move the preamble parsing here as it
+ -- can be part of (any) loaded (sub) file. The \starttext
+ -- wrapping might go away.
+
+ context.starttext()
+ context.xmlprocess("main",filename,"")
+ context.stoptext()
+
+ elseif suffix == "cld" or arguments.forcecld then
+
+ context.runfile(filename)
+
+ elseif suffix == "lua" or arguments.forcelua then
+
+ -- The wrapping might go away. Why is is it there in the
+ -- first place.
+
+ context.starttext()
+ context.ctxlua(string.format('dofile("%s")',filename))
+ context.stoptext()
+
+ elseif suffix == "mp" or arguments.forcemp then
+
+ context.starttext()
+ context.processMPfigurefile(filename)
+ context.stoptext()
+
+ -- elseif suffix == "prep" then
+ --
+ -- -- Why do we wrap here. Because it can be xml? Let's get rid
+ -- -- of prepping in general.
+ --
+ -- context.starttext()
+ -- context.input(filename)
+ -- context.stoptext()
+
+ else
+
+ -- We have a regular tex file so no \starttext yet as we can
+ -- load fonts.
+
+ context.input(filename)
+
+ end
+
+ context.finishjob()
+
+\stopluacode
+
+\endinput
diff --git a/tex/context/base/context-base.lmx b/tex/context/base/context-base.lmx
index 09817463b..2b093c3e1 100644
--- a/tex/context/base/context-base.lmx
+++ b/tex/context/base/context-base.lmx
@@ -19,7 +19,9 @@
<?lua end ?>
<style type="text/css">
<?lmx-include context.css ?>
- </style>
+ <?lua if v('cssdata') then ?>
+<?lua pv('cssdata') ?>
+ <?lua end ?> </style>
<?lua if v('styles') then for k, v in ipairs(v('styles')) do ?>
<link rel="StyleSheet" href="<?lua p(v) ?>" type="text/css" />
<?lua end end ?>
diff --git a/tex/context/base/context-help.lmx b/tex/context/base/context-help.lmx
index 5401fb65d..939b70cb6 100644
--- a/tex/context/base/context-help.lmx
+++ b/tex/context/base/context-help.lmx
@@ -19,6 +19,7 @@
</script>
<title><?lua pv('title') ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <!-- <base target="context-help" /> -->
<style type="text/css">
<!--
<?lmx-include context.css ?>
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 7b8733c88..5b6793083 100644
--- a/tex/context/base/context-version.pdf
+++ b/tex/context/base/context-version.pdf
Binary files differ
diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png
index bb280817c..2df1bdb1b 100644
--- a/tex/context/base/context-version.png
+++ b/tex/context/base/context-version.png
Binary files differ
diff --git a/tex/context/base/context.mkii b/tex/context/base/context.mkii
index 8cd02fd9e..3163097b0 100644
--- a/tex/context/base/context.mkii
+++ b/tex/context/base/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2012.05.30 11:26}
+\edef\contextversion{2012.10.19 00:06}
%D For those who want to use this:
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index 5044edae1..3d93b64c3 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -19,11 +19,13 @@
%D 2004.8.30 the low level interface is english. Watch out and adapt
%D your styles an modules.
+% \everypar{\writestatus{!!!!}{some spurious input in line \the\inputlineno}\wait}
+
%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{2012.05.30 11:26}
+\edef\contextversion{2012.10.19 00:06}
%D For those who want to use this:
@@ -107,9 +109,10 @@
\loadmarkfile{mult-ini}
\loadmarkfile{mult-sys}
+\loadmarkfile{mult-aux}
\loadmarkfile{mult-def}
\loadmarkfile{mult-chk}
-\loadmarkfile{mult-aux}
+%loadmarkfile{mult-aux} % moved up
\loadmkvifile{mult-dim}
\loadmarkfile{cldf-int} % interface
@@ -120,7 +123,7 @@
\loadmarkfile{attr-ini}
-\loadmarkfile{core-var}
+\loadmarkfile{core-ini}
\loadmarkfile{core-env}
\loadmarkfile{layo-ini}
@@ -131,7 +134,7 @@
\loadmarkfile{node-fin}
\loadmarkfile{node-mig}
-\loadmarkfile{node-par}
+\loadmarkfile{typo-bld} % par builders
%loadmarkfile{node-pag}
\loadmarkfile{back-ini}
@@ -142,24 +145,23 @@
\loadmarkfile{attr-eff}
\loadmarkfile{trac-tex}
-\loadmarkfile{trac-deb}
+\loadmarkfile{trac-deb} % will move up
+\loadmarkfile{trac-ctx} % maybe move up
%loadmarkfile{blob-ini} % not to be used, we only use a helper
\loadmarkfile{supp-box}
-\loadmarkfile{supp-vis}
-\loadmarkfile{supp-fun} % close to obsolete
+%loadmarkfile{supp-vis} % replaced by trac-vis
+%loadmarkfile{supp-fun} % mostly replaced
\loadmarkfile{supp-ran}
\loadmarkfile{supp-mat}
-\loadmarkfile{supp-ali}
-\loadmarkfile{supp-num} % replaced
+\loadmarkfile{spac-cha}
+%loadmarkfile{supp-num} % obsolete
\loadmarkfile{typo-ini}
-\loadmarkfile{page-ins}
-
\loadmkvifile{file-syn}
\loadmkvifile{file-mod}
@@ -186,7 +188,7 @@
\loadmarkfile{node-bck} % overloads anch-pgr (experimental and undocumented)
-\loadmarkfile{trac-vis}
+\loadmarkfile{pack-cut} % leftovers from trac-vis
\loadmarkfile{lang-mis}
\loadmarkfile{lang-url}
@@ -258,6 +260,7 @@
\loadmarkfile{page-var}
\loadmkvifile{page-otr}
\loadmarkfile{page-ini}
+\loadmarkfile{page-ins}
\loadmarkfile{page-fac}
\loadmarkfile{page-brk}
\loadmarkfile{page-col}
@@ -274,9 +277,10 @@
\loadmkvifile{strc-flt}
-\loadmarkfile{page-mis}
+\loadmarkfile{page-pst}
\loadmkvifile{page-mbk}
-\loadmarkfile{page-mul}
+\loadmarkfile{page-mul} % partly overloaded
+\loadmarkfile{page-mix} % new
\loadmarkfile{page-set}
\loadmarkfile{pack-lyr}
\loadmarkfile{pack-pos}
@@ -286,10 +290,11 @@
\loadmarkfile{page-par}
\loadmarkfile{typo-pag}
\loadmarkfile{typo-mar}
+\loadmarkfile{typo-itm}
\loadmarkfile{buff-ini}
\loadmarkfile{buff-ver}
-\loadmarkfile{buff-par}
+\loadmkvifile{buff-par}
\loadmarkfile{buff-imp-tex} % optional as also runtime if not loaded
\loadmarkfile{buff-imp-mp} % optional as also runtime if not loaded
@@ -302,14 +307,15 @@
\loadmarkfile{strc-blk}
\loadmarkfile{page-imp}
-\loadmarkfile{page-sel} % optional
-\loadmarkfile{page-com} % optional
+\loadmkvifile{page-sel} % optional
\loadmkvifile{scrn-pag}
\loadmkvifile{scrn-wid}
\loadmkvifile{scrn-but}
\loadmkvifile{scrn-bar}
+\loadmarkfile{page-com} % optional (after scrn-pag)
+
\loadmarkfile{strc-bkm} % bookmarks
\loadmarkfile{tabl-com}
@@ -323,6 +329,7 @@
\loadmarkfile{tabl-ltb}
\loadmarkfile{tabl-tsp}
\loadmkvifile{tabl-xtb}
+\loadmarkfile{tabl-mis}
\loadmarkfile{java-ini}
@@ -345,9 +352,11 @@
\loadmarkfile{font-pre}
\loadmarkfile{font-unk}
\loadmarkfile{font-tra}
+\loadmarkfile{font-chk}
\loadmarkfile{font-uni}
\loadmkvifile{font-col}
-\loadmarkfile{font-gds}
+\loadmkvifile{font-gds}
+\loadmkvifile{font-aux}
\loadmarkfile{lxml-css}
@@ -355,6 +364,8 @@
\loadmarkfile{blob-ini} % not to be used, we only use a helper
+\loadmarkfile{trac-vis}
+
\loadmarkfile{typo-cln}
\loadmarkfile{typo-spa}
\loadmarkfile{typo-krn}
@@ -380,6 +391,7 @@
\loadmarkfile{meta-tex}
\loadmarkfile{meta-fun}
\loadmarkfile{meta-pag}
+\loadmarkfile{meta-grd}
\loadmarkfile{page-mrk} % depends on mp
@@ -417,14 +429,12 @@
\loadmarkfile{typo-scr}
-\loadmarkfile{core-fnt}
\loadmarkfile{node-rul}
-\loadmarkfile{node-spl}
+\loadmkvifile{font-sol} % font solutions
\loadmkvifile{strc-not}
\loadmkvifile{strc-lnt}
-\loadmarkfile{core-mis}
\loadmarkfile{pack-com}
\loadmarkfile{typo-del}
@@ -454,9 +464,8 @@
\loadmarkfile{cldf-ver} % verbatim, this can come late
\loadmarkfile{cldf-com} % commands, this can come late
-\loadmarkfile{core-ctx}
+\loadmarkfile{core-ctx} % this order might change but we need to check depedencies / move to another namespace
-\loadmarkfile{core-ini}
\loadmarkfile{core-def}
%usemodule[x][res-04] % xml resource libraries
@@ -465,7 +474,7 @@
% now we hook in backend code (needs checking)
-\loadmarkfile{back-pdf} % actually, this one should load the next three
+\loadmarkfile{back-pdf} % actually, this one should load the next three using document.arguments.backend
\loadmarkfile{mlib-pdf}
\loadmarkfile{mlib-pps}
\loadmarkfile{meta-pdf}
diff --git a/tex/context/base/context.rme b/tex/context/base/context.rme
index 1ce6b25c0..ff9ffb8ac 100644
--- a/tex/context/base/context.rme
+++ b/tex/context/base/context.rme
@@ -14,7 +14,10 @@ real problem as the engines don't change much either.
Early 2011 the code base between MkII and MkIV got split completely
and there is no shared code any longer, apart from some styles and
-modules.
+modules. From the perspective of ConteXt we now consider XeTeX to be
+obsolete although we will keep supporting it in MkII. As pdftex is
+still used in older workflows we will support that as long as it's
+around.
The main files context.mkii and context.mkiv are normally not used
directly but instead we use the interface specific formats:
@@ -76,4 +79,4 @@ Don't hesitate to ask questions. ConTeXt can do a lot, but the manuals
always lag behind and can be incomplete.
-------------------------
-Hans Hagen, pragma@wxs.nl
+Hans Hagen, pragma @ wxs . nl
diff --git a/tex/context/base/context.todo b/tex/context/base/context.todo
deleted file mode 100644
index 27d914a7b..000000000
--- a/tex/context/base/context.todo
+++ /dev/null
@@ -1,6 +0,0 @@
-% marginrules
-
-% consistently use label/name/tag
-% consistently use type/kind
-
-% option vs options
diff --git a/tex/context/base/core-con.lua b/tex/context/base/core-con.lua
index e4b516e3b..641aea4ba 100644
--- a/tex/context/base/core-con.lua
+++ b/tex/context/base/core-con.lua
@@ -14,6 +14,8 @@ slower but look nicer this way.</p>
<p>Some code may move to a module in the language namespace.</p>
--ldx]]--
+local command, context = commands, context
+
local utf = unicode.utf8
local floor, date, time, concat = math.floor, os.date, os.time, table.concat
@@ -22,30 +24,29 @@ local utfchar, utfbyte = utf.char, utf.byte
local tonumber, tostring = tonumber, tostring
local settings_to_array = utilities.parsers.settings_to_array
-local allocate = utilities.storage.allocate
-
-local context = context
+local allocate = utilities.storage.allocate
-local variables = interfaces.variables
+local context = context
-converters = converters or { }
-local converters = converters
+local variables = interfaces.variables
-languages = languages or { }
-local languages = languages
+converters = converters or { }
+local converters = converters
-local function number(n)
- return tonumber(n)
-end
+languages = languages or { }
+local languages = languages
-converters.number = number
+converters.number = tonumber
+converters.numbers = tonumber
function commands.number(n) context(n) end
+commands.numbers = commands.number
+
-- to be reconsidered ... languages namespace here, might become local plus a register command
local counters = allocate {
- ['**'] = {
+ ['default'] = { -- no metatable as we do a test on keys
0x0061, 0x0062, 0x0063, 0x0064, 0x0065,
0x0066, 0x0067, 0x0068, 0x0069, 0x006A,
0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
@@ -135,7 +136,7 @@ counters['kr'] = counters['korean']
counters['kr-p'] = counters['korean-parent']
counters['kr-c'] = counters['korean-circle']
-local fallback = utf.byte('0')
+local fallback = utfbyte('0')
local function chr(n,m)
return (n > 0 and n < 27 and utfchar(n+m)) or ""
@@ -197,32 +198,28 @@ local function do_alphabetic(n,mapping,mapper,t)
end
end
-local function alphabetic(n,code)
- return do_alphabetic(n,counters[code] or counters['**'],lowercharacter)
+function converters.alphabetic(n,code)
+ return do_alphabetic(n,counters[code] or counters.default,lowercharacter)
end
-local function Alphabetic(n,code)
- return do_alphabetic(n,counters[code] or counters['**'],uppercharacter)
+function converters.Alphabetic(n,code)
+ return do_alphabetic(n,counters[code] or counters.default,uppercharacter)
end
-local function character (n) return chr (n,96) end
-local function Character (n) return chr (n,64) end
-local function characters(n) return chrs(n,96) end
-local function Characters(n) return chrs(n,64) end
-
-converters.alphabetic = alphabetic
-converters.Alphabetic = Alphabetic
-converters.character = character
-converters.Character = Character
-converters.characters = characters
-converters.Characters = Characters
-
-function commands.alphabetic(n,c) context(alphabetic(n,c)) end
-function commands.Alphabetic(n,c) context(Alphabetic(n,c)) end
-function commands.character (n) context(character (n)) end
-function commands.Character (n) context(Character (n)) end
-function commands.characters(n) context(characters(n)) end
-function commands.Characters(n) context(Characters(n)) end
+local lower_offset = 96
+local upper_offset = 64
+
+function converters.character (n) return chr (n,lower_offset) end
+function converters.Character (n) return chr (n,upper_offset) end
+function converters.characters(n) return chrs(n,lower_offset) end
+function converters.Characters(n) return chrs(n,upper_offset) end
+
+function commands.alphabetic(n,c) context(do_alphabetic(n,counters[c],lowercharacter)) end
+function commands.Alphabetic(n,c) context(do_alphabetic(n,counters[c],uppercharacter)) end
+function commands.character (n) context(chr (n,lower_offset)) end
+function commands.Character (n) context(chr (n,upper_offset)) end
+function commands.characters(n) context(chrs(n,lower_offset)) end
+function commands.Characters(n) context(chrs(n,upper_offset)) end
local days = {
[false] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
@@ -245,52 +242,35 @@ local function nofdays(year,month)
return days[isleapyear(year)][month]
end
-local function year () return date("%Y") end
-local function month () return date("%m") end
-local function hour () return date("%H") end
-local function minute() return date("%M") end
-local function second() return date("%S") end
-
local function textime()
return tonumber(date("%H")) * 60 + tonumber(date("%M"))
end
+function converters.year () return date("%Y") end
+function converters.month () return date("%m") end
+function converters.hour () return date("%H") end
+function converters.minute() return date("%M") end
+function converters.second() return date("%S") end
+
converters.weekday = weekday
converters.isleapyear = isleapyear
converters.leapyear = leapyear
converters.nofdays = nofdays
-converters.year = year
-converters.month = month
-converters.hour = hour
-converters.minute = minute
-converters.second = second
converters.textime = textime
-function commands.weekday(day,month,year)
- context(weekday(day,month,year))
-end
-
-function commands.isleapyear(year)
- context(isleapyear(year))
-end
-
-function commands.leapyear(year)
- context(leapyear(year))
-end
-
-function commands.nofdays(year,month)
- context(nofdays(year,month))
-end
+function commands.weekday (day,month,year) context(weekday (day,month,year)) end
+function commands.leapyear(year) context(leapyear(year)) end -- rather useless
+function commands.nofdays (year,month) context(nofdays (year,month)) end
-function commands.year () context(year ()) end
-function commands.month () context(month ()) end
-function commands.hour () context(hour ()) end
-function commands.minute () context(minute ()) end
-function commands.second () context(second ()) end
+function commands.year () context(date("%Y")) end
+function commands.month () context(date("%m")) end
+function commands.hour () context(date("%H")) end
+function commands.minute () context(date("%M")) end
+function commands.second () context(date("%S")) end
function commands.textime() context(textime()) end
function commands.doifleapyearelse(year)
- commands.testcase(leapyear(year))
+ commands.doifelse(isleapyear(year))
end
local roman = {
@@ -307,13 +287,9 @@ local function toroman(n)
end
end
-local Romannumerals = toroman
-
-local function romannumerals(n) return lower(toroman(n)) end
-
converters.toroman = toroman
converters.Romannumerals = toroman
-converters.romannumerals = romannumerals
+converters.romannumerals = function(n) return lower(toroman(n)) end
function commands.romannumerals(n) context(lower(toroman(n))) end
function commands.Romannumerals(n) context( toroman(n)) end
@@ -366,11 +342,8 @@ end
converters.toabjad = toabjad
-local function abjadnumerals (n) return toabjad(n,false) end
-local function abjadnodotnumerals(n) return toabjad(n,true ) end
-
-converters.abjadnumerals = abjadnumerals
-converters.abjadnodotnumerals = abjadnodotnumerals
+function converters.abjadnumerals (n) return toabjad(n,false) end
+function converters.abjadnodotnumerals(n) return toabjad(n,true ) end
function commands.abjadnumerals (n) context(toabjad(n,false)) end
function commands.abjadnodotnumerals(n) context(toabjad(n,true )) end
@@ -515,23 +488,18 @@ end
converters.tochinese = tochinese
-local function chinesenumerals (n) return tochinese(n,"normal") end
-local function chinesecapnumerals(n) return tochinese(n,"cap" ) end
-local function chineseallnumerals(n) return tochinese(n,"all" ) end
-
-converters.chinesenumerals = chinesenumerals
-converters.chinesecapnumerals = chinesecapnumerals
-converters.chineseallnumerals = chineseallnumerals
+function converters.chinesenumerals (n) return tochinese(n,"normal") end
+function converters.chinesecapnumerals(n) return tochinese(n,"cap" ) end
+function converters.chineseallnumerals(n) return tochinese(n,"all" ) end
function commands.chinesenumerals (n) context(tochinese(n,"normal")) end
function commands.chinesecapnumerals(n) context(tochinese(n,"cap" )) end
function commands.chineseallnumerals(n) context(tochinese(n,"all" )) end
converters.sequences = converters.sequences or { }
+local sequences = converters.sequences
-storage.register("converters/sequences", converters.sequences, "converters.sequences")
-
-local sequences = converters.sequences
+storage.register("converters/sequences", sequences, "converters.sequences")
function converters.define(name,set)
sequences[name] = settings_to_array(set)
@@ -683,7 +651,7 @@ end
-- context(escapes[n] or utfchar(n))
-- end
--
--- local lccodes, uccodes = characters.lccode, characters.uccode
+-- local lccodes, uccodes, safechar = characters.lccode, characters.uccode, commands.safechar
--
-- local function do_alphabetic(n,mapping,chr)
-- local max = #mapping
@@ -691,7 +659,7 @@ end
-- do_alphabetic(floor((n-1)/max),mapping,chr)
-- n = (n-1)%max+1
-- end
--- characters.flush(chr(n,mapping))
+-- safechar(chr(n,mapping))
-- end
--
-- local function lowercased(n,mapping) return characters.lccode(mapping[n] or fallback) end
@@ -705,8 +673,6 @@ end
-- do_alphabetic(n,counters[code] or counters['**'],uppercased)
-- end
--- --
-
local ordinals = {
english = function(n)
local two = n % 100
@@ -813,11 +779,12 @@ end
function commands.currentdate(str,currentlanguage) -- second argument false : no label
local list = utilities.parsers.settings_to_array(str)
+ local splitlabel = languages.labels.split or string.itself -- we need to get the loading order right
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 = languages.labels.split(entry)
+ local tag, plus = splitlabel(entry)
local ordinal, mnemonic, whatordinal = false, false, nil
if not tag then
tag = entry
diff --git a/tex/context/base/core-con.mkiv b/tex/context/base/core-con.mkiv
index 241d43165..cdc51eb23 100644
--- a/tex/context/base/core-con.mkiv
+++ b/tex/context/base/core-con.mkiv
@@ -20,35 +20,27 @@
\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
-%D one and a core one, but to keep things simple as well as
-%D preserve the overview, I decided against splitting.
+%D This module deals with all kind of conversions from numbers and dates. I
+%D considered splitting this module in a support one and a core one, but to keep
+%D things simple as well as preserve the overview, I decided against splitting.
\let\spr\firstofoneargument % separator
\let\stp\firstofoneargument % stopper
-% cleaner, some day:
-%
-% \def\isolateseparators % etex only, even works with list separator overloading
-% {\unexpanded\def\spr##1{{##1}}%
-% \unexpanded\def\stp##1{{##1}}}
-
-% needed for arab :
+% needed for arab:
\unexpanded\def\isolateseparators % even works with list separator overloading
- {\def\spr##1{{##1}}%
- \def\stp##1{{##1}}}
+ {\def\spr##1{{##1}}% % we can probably best mess around with zwj
+ \def\stp##1{{##1}}} % and friends
%D \macros
%D {numbers}
%D
-%D First we deal with the dummy conversion of numbers using the
-%D \TEX\ primitive \type{\number}. The uppercase alternative is
-%D only there for compatibility with the other conversion
-%D macros. We could do without \type{#1} but this way we get
-%D rid of unwanted braces. For the savety we also define a
-%D non||sence uppercase alternative.
+%D First we deal with the dummy conversion of numbers using the \TEX\ primitive
+%D \type{\number}. The uppercase alternative is only there for compatibility with
+%D the other conversion macros. We could do without \type{#1} but this way we get
+%D rid of unwanted braces. For the savety we also define a non||sence uppercase
+%D alternative.
%D
%D \showsetup{numbers}
%D
@@ -57,8 +49,8 @@
%D \def\Numbers#1{\number#1}
%D \stoptyping
%D
-%D Due to read ahead, as in \type{[\pagenumber\space]} the space will
-%D disappear, unless we use:
+%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear,
+%D unless we use:
\def\numbers#1{\purenumber{#1}}
\def\Numbers#1{\purenumber{#1}}
@@ -66,10 +58,9 @@
%D \macros
%D {romannumerals,Romannumerals}
%D
-%D \TEX\ the program uses a rather tricky conversion from
-%D numbers to their roman counterparts. This conversion could
-%D of course be programmed in \TEX\ itself, but I guess Knuth
-%D found the programming trick worth presenting.
+%D \TEX\ the program uses a rather tricky conversion from numbers to their roman
+%D counterparts. This conversion could of course be programmed in \TEX\ itself, but
+%D I guess Knuth found the programming trick worth presenting.
%D
%D \showsetup{romannumerals}
%D \showsetup{Romannumerals}
@@ -113,9 +104,9 @@
%D \macros
%D {character,Character}
%D
-%D Converting a number into a character can of course only
-%D be done with numbers less or equal to~26. At the cost of
-%D much more macros a faster conversion is possible, using:
+%D Converting a number into a character can of course only be done with numbers
+%D less or equal to~26. At the cost of much more macros a faster conversion is
+%D possible, using:
%D
%D \starttyping
%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}}
@@ -134,9 +125,8 @@
%D \macros
%D {characters,Characters}
%D
-%D Converting large numbers is supported by the next two
-%D macros. This time we just count on: $\cdots$~x, y, z, aa,
-%D ab, ac~$\cdots$.
+%D Converting large numbers is supported by the next two macros. This time we
+%D just count on: $\cdots$~x, y, z, aa, ab, ac~$\cdots$.
%D
%D \showsetup{characters}
%D \showsetup{Characters}
@@ -163,20 +153,25 @@
\endgroup}
\unexpanded\def\oldstyleromannumerals#1% will become obsolete
- {\begingroup
- \leftrulefalse
- \rightrulefalse
+ {\dontleavehmode
+ \hbox\bgroup
\ss\txx
- \boxrulewidth.15ex
- \ruledhbox spread .15em{\hss\uppercased{\romannumerals{#1}}\hss}%
- \endgroup}
+ \setbox\scratchbox\hbox \s!spread .15\emwidth{\hss\uppercased{\romannumerals{#1}}\hss}%
+ \scratchwidth \wd\scratchbox
+ \scratchheight\ht\scratchbox
+ \scratchdimen .1\exheight
+ \vrule\s!width\scratchwidth\s!height\dimexpr\scratchheight+\scratchdimen\relax\s!depth-\dimexpr\scratchheight-+\scratchdimen\relax
+ \hskip-\scratchwidth
+ \vrule\s!width\scratchwidth\s!height\scratchdimen\s!depth\scratchdimen
+ \hskip-\scratchwidth
+ \box\scratchbox
+ \egroup}
%D \macros
%D {protectconversion}
%D
-%D The previous two commands are not robust enough to be
-%D passed to \type{\write} en \type{\message}. That's why we
-%D introduce:
+%D The previous two commands are not robust enough to be passed to \type
+%D {\write} en \type{\message}. That's why we introduce:
\unexpanded\def\protectconversion
{\let\doconvertcharacters\firstofoneargument}
@@ -184,10 +179,9 @@
%D \macros
%D {normaltime,normalyear,normalmonth,normalday}
%D
-%D The last part of this module is dedicated to converting
-%D dates. Because we want to use as meaningful commands as
-%D possible, and because \TEX\ already uses up some of those,
-%D we save the original meanings.
+%D The last part of this module is dedicated to converting dates. Because we
+%D want to use as meaningful commands as possible, and because \TEX\ already
+%D uses up some of those, we save the original meanings.
\savenormalmeaning\time
\savenormalmeaning\year
@@ -197,10 +191,9 @@
%D \macros
%D {month,MONTH}
%D
-%D Converting the month number into a month name is done
-%D using a case statement, abstact values and the label
-%D mechanism. This way users can easily redefine a label from
-%D for instance german into austrian.
+%D Converting the month number into a month name is done using a case statement,
+%D abstact values and the label mechanism. This way users can easily redefine a
+%D label from for instance german into austrian.
%D
%D \starttyping
%D \setuplabeltext [de] [january=J\"anner]
@@ -224,11 +217,9 @@
\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
-%D week. In doing so, we have to calculate the total number of
-%D days, taking leapyears into account. For those who are
-%D curious:
+%D We never explicitly needed this, but Tobias Burnus pointed out that it would be
+%D handy to convert to the day of the week. In doing so, we have to calculate the
+%D total number of days, taking leapyears into account. For those who are curious:
%D
%D \startitemize[packed]
%D \item years that can be divided by 4 are leapyears
@@ -239,8 +230,7 @@
%D \macros
%D {weekday,WEEKDAY}
%D
-%D The first one is sort of redundant. It takes the day
-%D number argument.
+%D The first one is sort of redundant. It takes the day number argument.
%D
%D \showsetup{weekday}
%D \showsetup{WEEKDAY}
@@ -277,15 +267,15 @@
%D \getbuffer
%D \stoplines
%D
-%D The macro \type {\getdayoftheweek} can be used to calculate
-%D the number \type {\normalweekday}.
+%D The macro \type {\getdayoftheweek} can be used to calculate the number
+%D \type {\normalweekday}.
%D \macros
%D {doifleapyearelse,
%D getdayspermonth}
%D
-%D Sometimes we need to know if we're dealing with a
-%D leapyear, so here is a testmacro:
+%D Sometimes we need to know if we're dealing with a leapyear, so here is a
+%D testmacro:
%D
%D \starttyping
%D \doifleapyearelse{year}{yes}{no}
@@ -297,8 +287,7 @@
%D \getdayspermonth{year}{month}
%D \stoptyping
%D
-%D The number of days is available in the macro \type
-%D {\numberofdays}.
+%D The number of days is available in the macro \type {\numberofdays}.
\def\doifleapyearelse#1%
{\ctxcommand{doifleapyearelse(\number#1)}}
@@ -320,13 +309,11 @@
%D \macros
%D {currentdate, rawdate, date}
%D
-%D We use these conversion macros in the date formatting
-%D macro:
+%D We use these conversion macros in the date formatting macro:
%D
%D \showsetup{currentdate}
%D
-%D This macro takes care of proper spacing and delivers for
-%D instance:
+%D This macro takes care of proper spacing and delivers for instance:
%D
%D \startbuffer
%D \currentdate[weekday,day,month,year] % still dutch example
@@ -351,8 +338,8 @@
%D
%D or typeset: \getbuffer.
%D
-%D When no argument is passed, the current date is given as
-%D specified per language (using \type{\installlanguage}).
+%D When no argument is passed, the current date is given as specified per
+%D language (using \type{\installlanguage}).
%D
%D \showsetup{currentdate}
%D
@@ -367,8 +354,8 @@
%D
%D \typebuffer
%D
-%D The date is specified by one character keys. When no date
-%D is given, we get the current date.
+%D The date is specified by one character keys. When no date is given, we
+%D get the current date.
%D
%D \startlines
%D \getbuffer
@@ -430,10 +417,13 @@
\def\syst_converters_date[#1][#2]%
{\begingroup
\iffirstargument
- \getparameters[\??da][d=\normalday,m=\normalmonth,y=\normalyear,#1]%
- \normalday \@@dad\relax
- \normalmonth\@@dam\relax
- \normalyear \@@day\relax
+ \letdummyparameter\c!d\normalday
+ \letdummyparameter\c!m\normalmonth
+ \letdummyparameter\c!y\normalyear
+ \getdummyparameters[#1]%
+ \normalday \directdummyparameter\c!d\relax
+ \normalmonth\directdummyparameter\c!m\relax
+ \normalyear \directdummyparameter\c!y\relax
\fi
\syst_converters_current_date[#2]%
\endgroup}
@@ -444,9 +434,8 @@
%D \macros
%D {currenttime}
%D
-%D The currenttime is actually the jobtime. You can specify
-%D a pattern similar to the previous date macro using the
-%D keys \type {h}, \type {m} and a separator.
+%D The currenttime is actually the jobtime. You can specify a pattern similar
+%D to the previous date macro using the keys \type {h}, \type {m} and a separator.
\unexpanded\def\calculatecurrenttime
{\edef\currenthour {\ctxcommand{hour ()}}%
@@ -462,7 +451,6 @@
\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]}
@@ -471,16 +459,15 @@
{\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}}
-%D Because we're dealing with dates, we also introduce a few
-%D day loops:
+%D Because we're dealing with dates, we also introduce a few day loops:
%D
%D \starttyping
%D \processmonth{year}{month}{command}
%D \processyear{year}{command}{before}{after}
%D \stoptyping
%D
-%D The counters \type {\normalyear}, \type {\normalmonth} and
-%D \type{\normalday} can be used for for date manipulations.
+%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday}
+%D can be used for for date manipulations.
\unexpanded\def\processmonth#1#2#3% year month command
{\begingroup
@@ -505,15 +492,13 @@
%D \macros
%D {defineconversion, convertnumber}
%D
-%D Conversion involves the macros that we implemented earlier
-%D in this module.
+%D Conversion involves the macros that we implemented earlier in this module.
%D
%D \showsetup{defineconversion}
%D \showsetup{convertnumber}
%D
-%D We can feed this command with conversion macros as well as
-%D a set of conversion symbols. Both need a bit different
-%D treatment.
+%D We can feed this command with conversion macros as well as a set of conversion
+%D symbols. Both need a bit different treatment.
%D
%D \starttyping
%D \defineconversion [roman] [\romannumerals]
@@ -549,9 +534,9 @@
\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.
+%D If a conversion is just a font switch then we need to make sure that the
+%D number is indeed ends up as number in the input, so we need to handle the
+%D second argument.
\def\convertnumber#1#2% expandable
{\csname\??conversionarguments
@@ -600,19 +585,17 @@
%D \macros
%D {ordinaldaynumber, highordinalstr, ordinalstr}
%D
-%D Efficient general ordinal number converters are sometimes
-%D difficult to implement. Fortunately dates never exceed the
-%D number~31.
+%D Efficient general ordinal number converters are sometimes difficult to
+%D implement. Fortunately dates never exceed the number~31.
\def\highordinalstr #1{\high{\notsmallcapped{#1}}}
\def\ordinalstr #1{\notsmallcapped{#1}}
\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
-%D itemization macros, we prefer symbols because they can more
-%D easier be (partially) redefined. Symbols are implemented
-%D in another module.
+%D As longs as symbols are linked to levels or numbers, we can also use the
+%D conversion mechanism, but in for instance the itemization macros, we prefer
+%D symbols because they can more easier be (partially) redefined. Symbols are
+%D implemented in another module.
\def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}}
\def\smallcappedcharacters #1{\smallcapped{\characters {#1}}}
diff --git a/tex/context/base/core-ctx.ctx b/tex/context/base/core-ctx.ctx
new file mode 100644
index 000000000..5126ad2d2
--- /dev/null
+++ b/tex/context/base/core-ctx.ctx
@@ -0,0 +1,23 @@
+<?xml version='1.0' standalone='yes'?>
+
+<ctx:job>
+ <ctx:message>demo file</ctx:message>
+ <ctx:preprocess suffix='prep'>
+ <ctx:processors>
+ <ctx:processor name='step-1' suffix='one' >dummy-prep-command-1 <ctx:value name='old'/> <ctx:value name='new'/></ctx:processor>
+ <ctx:processor name='step-2' suffix='prep'>dummy-prep-command-2 <ctx:value name='old'/> <ctx:value name='new'/></ctx:processor>
+ </ctx:processors>
+ <ctx:files>
+ <ctx:file processor='step-1' >one*.xml</ctx:file>
+ <ctx:file processor='step-2' >two*.xml</ctx:file>
+ <ctx:file processor='step-1,step-2'>all*.xml</ctx:file>
+ </ctx:files>
+ </ctx:preprocess>
+ <ctx:process>
+ <ctx:resources>
+ <ctx:environment>step-1-step-2.tex</ctx:environment>
+ </ctx:resources>
+ </ctx:process>
+ <ctx:postprocess>
+ </ctx:postprocess>
+</ctx:job>
diff --git a/tex/context/base/core-ctx.lua b/tex/context/base/core-ctx.lua
index e6fb7bb5f..0dfb21ce9 100644
--- a/tex/context/base/core-ctx.lua
+++ b/tex/context/base/core-ctx.lua
@@ -6,72 +6,290 @@ if not modules then modules = { } end modules ['core-ctx'] = {
license = "see context related readme files"
}
+--[[
+Job control files aka ctx files are rather old and date from the mkii times.
+They were handled in texexec and mtx-context and deals with modes, modules,
+environments and preprocessing in projects where one such file drives the
+processing of lots of files without the need to provide command line
+arguments.
+
+In mkiv this concept was of course supported as well. The first implementation
+of mtx-context took much of the approach of texexec, but by now we have gotten
+rid of the option file (for passing modes, modules and environments), the stubs
+(for directly processing cld and xml) as well as the preprocessing component
+of the ctx files. Special helper features, like typesetting listings, were
+already moved to the extras (a direct side effect of the ability to pass along
+command line arguments.) All this made mtx-context more simple than its ancestor
+texexec.
+
+Because some of the modes might affect the mtx-context end, the ctx file is
+still loaded there but only for getting the modes. The file is loaded again
+during the run but as loading and basic processing takes less than a
+millisecond it's not that much of a burden.
+--]]
+
+-- the ctxrunner tabel might either become private or move to the job namespace
+-- which also affects the loading order
+
local trace_prepfiles = false trackers.register("system.prepfiles", function(v) trace_prepfiles = v end)
+local gsub, find, match, validstring = string.gsub, string.find, string.match, string.valid
+local concat = table.concat
+local xmltext = xml.text
+
local report_prepfiles = logs.reporter("system","prepfiles")
commands = commands or { }
local commands = commands
-local list, suffix, islocal, found = { }, "prep", false, false
-
-function commands.loadctxpreplist()
- local ctlname = file.replacesuffix(tex.jobname,"ctl")
- if lfs.isfile(ctlname) then
- local x = xml.load(ctlname)
- if x then
- islocal = xml.found(x,"ctx:preplist[@local=='yes']")
---~ if trace_prepfiles then
- if islocal then
- report_prepfiles("loading ctx log file (local)") -- todo: m!system
- else
- report_prepfiles("loading ctx log file (specified)") -- todo: m!system
+ctxrunner = ctxrunner or { }
+
+ctxrunner.prepfiles = utilities.storage.allocate()
+
+local function dontpreparefile(t,k)
+ return k -- we only store when we have a prepper
+end
+
+table.setmetatableindex(ctxrunner.prepfiles,dontpreparefile)
+
+local function filtered(str,method) -- in resolvers?
+ str = tostring(str)
+ if method == 'name' then str = file.nameonly(str)
+ elseif method == 'path' then str = file.dirname(str)
+ elseif method == 'suffix' then str = file.suffix(str)
+ elseif method == 'nosuffix' then str = file.removesuffix(str)
+ elseif method == 'nopath' then str = file.basename(str)
+ elseif method == 'base' then str = file.basename(str)
+-- elseif method == 'full' then
+-- elseif method == 'complete' then
+-- elseif method == 'expand' then -- str = file.expandpath(str)
+ end
+ return (gsub(str,"\\","/"))
+end
+
+-- local function substitute(e,str)
+-- local attributes = e.at
+-- if str and attributes then
+-- if attributes['method'] then
+-- str = filtered(str,attributes['method'])
+-- end
+-- if str == "" and attributes['default'] then
+-- str = attributes['default']
+-- end
+-- end
+-- return str
+-- end
+
+local function substitute(str)
+ return str
+end
+
+local function justtext(str)
+ str = xml.unescaped(tostring(str))
+ str = xml.cleansed(str)
+ str = gsub(str,"\\+",'/')
+ str = gsub(str,"%s+",' ')
+ return str
+end
+
+function ctxrunner.load(ctxname)
+
+ local xmldata = xml.load(ctxname)
+
+ local jobname = tex.jobname -- todo
+
+ local variables = { job = jobname }
+ local commands = { }
+ local flags = { }
+ local paths = { } -- todo
+ local treatments = { }
+ local suffix = "prep"
+
+ xml.include(xmldata,'ctx:include','name', {'.', file.dirname(ctxname), "..", "../.." })
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do
+ local flag = xmltext(e)
+ local key, value = match(flag,"^(.-)=(.+)$")
+ if key and value then
+ environment.setargument(key,value)
+ else
+ environment.setargument(flag,true)
+ end
+ end
+
+ -- add to document.options.ctxfile[...]
+
+ local ctxfile = document.options.ctxfile
+
+ local modes = ctxfile.modes
+ local modules = ctxfile.modules
+ local environments = ctxfile.environments
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:mode") do
+ modes[#modes+1] = xmltext(e)
+ -- context.enablemode { xmltext(e) }
+ end
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:module") do
+ modules[#modules+1] = xmltext(e)
+ -- context.module { xmltext(e) }
+ end
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:environment") do
+ environments[#environments+1] = xmltext(e)
+ -- context.environment { xmltext(e) }
+ end
+
+ for e in xml.collected(xmldata,"ctx:message") do
+ report_prepfiles("ctx comment: %s", xmltext(e))
+ end
+
+ for r, d, k in xml.elements(xmldata,"ctx:value[@name='job']") do
+ d[k] = variables['job'] or ""
+ end
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do
+ commands[e.at and e.at['name'] or "unknown"] = e
+ end
+
+ local suffix = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/attribute('suffix')") -- or ...
+ local runlocal = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/ctx:processors/attribute('local')")
+
+ runlocal = toboolean(runlocal)
+
+ -- todo: only collect, then plug into file handler
+
+ local inputfile = validstring(environment.arguments.input) or jobname
+
+ variables.old = inputfile
+
+ for files in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:files") do
+ for pattern in xml.collected(files,"ctx:file") do
+ local preprocessor = pattern.at['processor'] or ""
+ for r, d, k in xml.elements(pattern,"/ctx:old") do
+ d[k] = jobname
+ end
+ for r, d, k in xml.elements(pattern,"/ctx:value[@name='old'") do
+ d[k] = jobname
+ end
+ pattern =justtext(xml.tostring(pattern))
+ if preprocessor and preprocessor ~= "" and pattern and pattern ~= "" then
+ local noftreatments = #treatments + 1
+ local findpattern = string.topattern(pattern)
+ local preprocessors = utilities.parsers.settings_to_array(preprocessor)
+ treatments[noftreatments] = {
+ pattern = findpattern,
+ preprocessors = preprocessors,
+ }
+ report_prepfiles("step: %s, pattern: %q, preprocessor: %q",noftreatments,findpattern,concat(preprocessors," "))
+ end
+ end
+ end
+
+ local function needstreatment(oldfile)
+ for i=1,#treatments do
+ local treatment = treatments[i]
+ local pattern = treatment.pattern
+ if find(oldfile,pattern) then
+ return treatment
+ end
+ end
+ end
+
+ local preparefile = #treatments > 0 and function(prepfiles,filename)
+
+ local treatment = needstreatment(filename)
+ if treatment then
+ local oldfile = filename
+ -- newfile = oldfile .. "." .. suffix
+ newfile = oldfile .. ".prep"
+ if runlocal then
+ newfile = file.basename(newfile)
+ end
+
+ if file.needsupdating(oldfile,newfile) then
+ local preprocessors = treatment.preprocessors
+ local runners = { }
+ for i=1,#preprocessors do
+ local preprocessor = preprocessors[i]
+ local command = commands[preprocessor]
+ if command then
+ command = xml.copy(command)
+ local suf = command.at and command.at['suffix'] or suffix
+ if suf then
+ newfile = oldfile .. "." .. suf
+ end
+ if runlocal then
+ newfile = file.basename(newfile)
+ end
+ for r, d, k in xml.elements(command,"ctx:old") do
+ d[k] = substitute(oldfile)
+ end
+ for r, d, k in xml.elements(command,"ctx:new") do
+ d[k] = substitute(newfile)
+ end
+ variables.old = oldfile
+ variables.new = newfile
+ for r, d, k in xml.elements(command,"ctx:value") do
+ local ek = d[k]
+ local ekat = ek.at and ek.at['name']
+ if ekat then
+ d[k] = substitute(variables[ekat] or "")
+ end
+ end
+ command = xml.content(command)
+ runners[#runners+1] = justtext(command)
+ oldfile = newfile
+ if runlocal then
+ oldfile = file.basename(oldfile)
+ end
+ end
end
---~ end
- for e in xml.collected(x,"ctx:prepfile") do
- local name = xml.text(e)
- if islocal then
- name = file.basename(name)
+ -- for tracing we have collected commands first
+ for i=1,#runners do
+ report_prepfiles("step %i: %s",i,runners[i])
end
- local done = e.at['done'] or 'no'
- if trace_prepfiles then
- report_prepfiles("registering %s -> %s",done)
+ --
+ for i=1,#runners do
+ local command = runners[i]
+ report_prepfiles("command: %s",command)
+ local result = os.spawn(command) or 0
+ -- if result > 0 then
+ -- report_prepfiles("error, return code: %s",result)
+ -- end
end
- found = true
- list[name] = done -- 'yes' or 'no'
+ if lfs.isfile(newfile) then
+ file.syncmtimes(filename,newfile)
+ report_prepfiles("%q is converted to %q",filename,newfile)
+ else
+ report_prepfiles("%q is not converted to %q",filename,newfile)
+ newfile = filename
+ end
+ elseif lfs.isfile(newfile) then
+ report_prepfiles("%q is already converted to %q",filename,newfile)
+ else
+ -- report_prepfiles("%q is not converted to %q",filename,newfile)
+ newfile = filename
end
+ else
+ newfile = filename
end
- end
-end
+ prepfiles[filename] = newfile
--- -- --
+ return newfile
-local function found(name) -- used in resolve
- local prepname = name .. "." .. suffix
- if list[name] and lfs.isfile(prepname) then
- if trace_prepfiles then
- report_prepfiles("preprocessing: using %s",prepname)
- end
- return prepname
end
- return false
+
+ table.setmetatableindex(ctxrunner.prepfiles,preparefile or dontpreparefile)
+
+ -- we need to deal with the input filename as it has already be resolved
+
end
local function resolve(name) -- used a few times later on
- local filename = file.collapsepath(name)
- local prepname = islocal and found(file.basename(name))
- if prepname then
- return prepname
- end
- prepname = found(filename)
- if prepname then
- return prepname
- end
- return false
+ return ctxrunner.prepfiles[file.collapsepath(name)] or false
end
---~ support.doiffileexistelse(name)
-
local processfile = commands.processfile
local doifinputfileelse = commands.doifinputfileelse
@@ -94,3 +312,24 @@ end
function commands.preparedfile(name)
return resolve(name) or name
end
+
+function commands.getctxfile()
+ local ctxfile = document.arguments.ctx or ""
+ if ctxfile ~= "" then
+ ctxrunner.load(ctxfile) -- do we need to locate it?
+ end
+end
+
+function ctxrunner.resolve(name) -- used a few times later on
+ return ctxrunner.prepfiles[file.collapsepath(name)] or name
+end
+
+-- ctxrunner.load("t:/sources/core-ctx.ctx")
+--
+-- context(ctxrunner.prepfiles["one-a.xml"]) context.par()
+-- context(ctxrunner.prepfiles["one-b.xml"]) context.par()
+-- context(ctxrunner.prepfiles["two-c.xml"]) context.par()
+-- context(ctxrunner.prepfiles["two-d.xml"]) context.par()
+-- context(ctxrunner.prepfiles["all-x.xml"]) context.par()
+--
+-- inspect(ctxrunner.prepfiles)
diff --git a/tex/context/base/core-ctx.mkiv b/tex/context/base/core-ctx.mkiv
index e178ee21b..50b3ae4a2 100644
--- a/tex/context/base/core-ctx.mkiv
+++ b/tex/context/base/core-ctx.mkiv
@@ -13,18 +13,16 @@
\writestatus{loading}{ConTeXt Core Macros / Job Control}
-\unprotect
-
-\setnewconstant\preprocessmethod\plustwo % always check in mkiv
-
\registerctxluafile{core-ctx}{1.000}
-\def\loadctxpreplist
- {\ctxcommand{loadctxpreplist()}%
- \glet\loadctxpreplist\relax}
+\unprotect
-\appendtoks
- \loadctxpreplist
-\to \everystarttext % maybe too late but don't change it now
+\unexpanded\def\job_options_get_commandline {\ctxcommand{getcommandline()}}
+\unexpanded\def\job_options_get_ctxfile {\ctxcommand{getctxfile()}}
+\unexpanded\def\job_options_log {\ctxcommand{logoptions()}}
+\unexpanded\def\job_options_set_modes {\ctxcommand{setdocumentmodes()}}
+\unexpanded\def\job_options_set_modules {\ctxcommand{setdocumentmodules()}}
+\unexpanded\def\job_options_set_environments{\ctxcommand{setdocumentenvironments()}}
+\unexpanded\def\job_options_set_filenames {\ctxcommand{setdocumentfilenames()}}
\protect \endinput
diff --git a/tex/context/base/core-dat.lua b/tex/context/base/core-dat.lua
index 071a3fe0b..879ff6130 100644
--- a/tex/context/base/core-dat.lua
+++ b/tex/context/base/core-dat.lua
@@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['core-dat'] = {
replaces the twopass data mechanism.</p>
--ldx]]--
-local tonumber = tonumber
+local tonumber, type = tonumber, type
local context, commands = context, commands
@@ -69,7 +69,12 @@ local function setdata(settings)
local tag = settings.tag
local data = settings.data
local list = tobesaved[name]
- data = settings_to_hash(data) or { }
+ if settings.convert and type(data) == "string" then
+ data = settings_to_hash(data)
+ end
+ if type(data) ~= "table" then
+ data = { data = settings.data }
+ end
if not tag then
tag = #list + 1
else
@@ -109,25 +114,30 @@ end
function datasets.getdata(name,tag,key,default)
local t = collected[name]
- if t then
+ if t == nil then
+ if trace_datasets then
+ report_dataset("unknown: name %s",name)
+ end
+ elseif type(t) ~= "table" then
+ return t
+ else
t = t[tag] or t[tonumber(tag)]
- if t then
- if key then
- return t[key] or default
- else
- return t
+ if not t then
+ if trace_datasets then
+ report_dataset("unknown: name %s, tag %s",name,tag)
end
- elseif trace_datasets then
- report_dataset("unknown: name %s, tag %s",name,tag)
+ elseif key then
+ return t[key] or default
+ else
+ return t
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)
+ settings.convert = true
+ local name, tag = setdata(settings)
if settings.delay ~= v_yes then
--
elseif type(tag) == "number" then
@@ -139,11 +149,25 @@ 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)
+ if t == nil then
+ if trace_datasets then
+ report_dataset("unknown: name %s (not passed to tex)",name)
+ end
+ elseif type(t) ~= "table" then
+ context(tostring(t))
+ else
+ t = t and (t[tag] or t[tonumber(tag)])
+ if not t then
+ if trace_datasets then
+ report_dataset("unknown: name %s with tag %s (not passed to tex)",name,tag)
+ end
+ elseif type(t) ~= "table" then
+ local s = t[key]
+ if type(s) ~= "table" then
+ context(tostring(s))
+ elseif trace_datasets then
+ report_dataset("table: name %s, tag %s (not passed to tex)",name,tag)
+ end
end
end
end
diff --git a/tex/context/base/core-def.mkiv b/tex/context/base/core-def.mkiv
index 4f856f996..d1c774f40 100644
--- a/tex/context/base/core-def.mkiv
+++ b/tex/context/base/core-def.mkiv
@@ -24,44 +24,116 @@
\setupinteraction[\c!symbolset=navigation 1]
+% what a mess
+
+\everypar \emptytoks
+\neverypar \emptytoks
+
+\appendtoks
+ % \flushnotes
+ \page_otr_command_synchronize_side_floats % an otr specific command
+ \checkindentation
+ \showparagraphnumber
+ \restoreinterlinepenalty
+ % \flushmargincontents
+ % \flushcommentanchors
+ \flushnotes
+ \synchronizenotes
+ \OTRSETshowstatus
+ \registerparoptions
+ % \flushsyncpositions
+ \flushpostponednodedata
+ \typo_delimited_repeat
+ \insertparagraphintro
+\to \everypar
+
+\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
+
% initialization order:
\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
+\appendtoks
+ \font_preloads_at_start_text
+\to \everystarttext
+
+\appendtoks
+ \font_preloads_at_stop_text
+\to \everystoptext
+
+\appendtoks
+ \showcontextbanner
+ \initializenewlinechar
+ \calculatecurrenttime
+ \loadsystemfiles
+ % \loadoptionfile % obsolete, but nice to keep as reference of when/how
+ \job_options_get_commandline % expands some commands
+ \job_options_get_ctxfile % might expand some commands
+ \job_options_set_filenames
+ \font_preloads_at_every_job
+ \settopskip % brrr
+ \initializemainlanguage
+ \initializexmlprocessing % is this still needed?
+ \initializepagebackgrounds
+ \initializepagecounters
+ % \directsetup{*runtime:options}% % obsolete as the option file is replaced by a more direct mechanism
+ % \directsetup{*runtime:modules}% % obsolete as the option file is replaced by a more direct mechanism
+ \job_options_set_modes
+ \job_options_set_modules
+ \job_options_set_environments
+\to \everyjob
-%prependtoks \preloadtypescript \to \everyjob
-\appendtoks \showcontextbanner \to \everyjob
-\appendtoks \initializenewlinechar \to \everyjob
-\appendtoks \calculatecurrenttime \to \everyjob
-\appendtoks \loadsystemfiles \to \everyjob
-\appendtoks \loadoptionfile \to \everyjob % can load files !
-\appendtoks \font_preloads_at_every_job \to \everyjob
-\appendtoks \settopskip \to \everyjob
-\appendtoks \initializemainlanguage \to \everyjob
-%appendtoks \MPLIBregister \to \everyjob
-\appendtoks \xmlinitialize \to \everyjob
-\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
+ \job_options_log
+\to \everystarttext
-%appendtoks \page[\v!last] \page \to \everybye % moved to core-job, we need to do this cleaner
-\appendtoks \ifarrangingpages\poparrangedpages\fi \to \everybye
-%appendtoks \registerfileinfo[end]\jobfilename \to \everybye
+\appendtoks
+ \ifarrangingpages\poparrangedpages\fi
+\to \everybye
-%appendtoks \MPLIBallocate{1000} \to \everydump
+\prependtoks
+ \resetallattributes
+\to \everybeforeoutput
-\prependtoks \resetallattributes \to \everybeforeoutput
+\appendtoks
+ \the\everybackendshipout
+\to \everyshipout
-\appendtoks \the\everybackendshipout \to \everyshipout
-\prependtoks \the\everylastbackendshipout \to \everylastshipout
+\prependtoks
+ \the\everylastbackendshipout
+\to \everylastshipout
-\prependtoks \lefttoright \to \everybeforeoutput
+\prependtoks
+ \lefttoright
+\to \everybeforeoutput
% temporary here:
@@ -88,4 +160,6 @@
% \resetcharacterspacing
% \to \everyhyphenatedurl
+% \setbreakpoints[compound]
+
\protect \endinput
diff --git a/tex/context/base/core-env.lua b/tex/context/base/core-env.lua
index c31df929e..8b9ae172b 100644
--- a/tex/context/base/core-env.lua
+++ b/tex/context/base/core-env.lua
@@ -37,7 +37,7 @@ setmetatableindex(tex.modes, function(t,k)
if m then
return m()
else
- local n = "mode" .. k
+ local n = "mode>" .. k
if csname_id(n) == undefined then
return false
else
@@ -52,7 +52,7 @@ setmetatableindex(tex.systemmodes, function(t,k)
if m then
return m()
else
- local n = "mode*" .. k
+ local n = "mode>*" .. k
if csname_id(n) == undefined then
return false
else
@@ -122,12 +122,15 @@ local types = {
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
diff --git a/tex/context/base/core-env.mkiv b/tex/context/base/core-env.mkiv
index 1819d084d..38d3b1b29 100644
--- a/tex/context/base/core-env.mkiv
+++ b/tex/context/base/core-env.mkiv
@@ -54,42 +54,44 @@
% fast internal ones
+\def\??mode{mode>} % special namespace, also used at lua end
+
\def\syst_modes_new#1%
- {\expandafter\newcount\csname\s!mode#1\endcsname}
+ {\expandafter\newcount\csname\??mode#1\endcsname}
\unexpanded\def\newmode#1%
- {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi}
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi}
\unexpanded\def\setmode#1%
- {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
- \csname\s!mode#1\endcsname\enabledmode}
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \csname\??mode#1\endcsname\enabledmode}
\unexpanded\def\resetmode#1%
- {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
- \csname\s!mode#1\endcsname\disabledmode}
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \csname\??mode#1\endcsname\disabledmode}
\unexpanded\def\newsystemmode#1%
- {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi}
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi}
\unexpanded\def\setsystemmode#1%
- {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
- \csname\s!mode\systemmodeprefix#1\endcsname\enabledmode}
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \csname\??mode\systemmodeprefix#1\endcsname\enabledmode}
\unexpanded\def\resetsystemmode#1%
- {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
- \csname\s!mode\systemmodeprefix#1\endcsname\disabledmode}
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \csname\??mode\systemmodeprefix#1\endcsname\disabledmode}
% \def\dosetsystemmode#1%
-% {\csname\s!mode\systemmodeprefix#1\endcsname\enabledmode}
+% {\csname\??mode\systemmodeprefix#1\endcsname\enabledmode}
%
% \def\doresetsystemmode#1%
-% {\csname\s!mode\systemmodeprefix#1\endcsname\disabledmode}
+% {\csname\??mode\systemmodeprefix#1\endcsname\disabledmode}
% demo: trialtypesetting is a systemmode as well as an if
\newsystemmode{trialtypesetting} % the name of \@@trialtypesetting might change (also at the lua end)
-\expandafter\let\expandafter\@@trialtypesetting\csname\s!mode\systemmodeprefix trialtypesetting\endcsname % private !
+\expandafter\let\expandafter\@@trialtypesetting\csname\??mode\systemmodeprefix trialtypesetting\endcsname % private !
\appendtoks
\@@trialtypesetting\enabledmode
@@ -112,25 +114,25 @@
\def\syst_modes_disable[#1]{\protect\rawprocesscommacommand[#1]\syst_modes_disable_indeed}
\def\syst_modes_prevent_indeed#1%
- {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
- \csname\s!mode#1\endcsname\preventedmode}
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \csname\??mode#1\endcsname\preventedmode}
\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
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \ifnum\csname\??mode#1\endcsname=\preventedmode \else
+ \csname\??mode#1\endcsname\enabledmode
\fi}
\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
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \ifnum\csname\??mode#1\endcsname=\preventedmode \else
+ \csname\??mode#1\endcsname\disabledmode
\fi}
% handy for mp
\def\booleanmodevalue#1%
- {\ifcsname\s!mode#1\endcsname\ifcase\csname\s!mode#1\endcsname\s!false\else\s!true\fi\else\s!false\fi}
+ {\ifcsname\??mode#1\endcsname\ifcase\csname\??mode#1\endcsname\s!false\else\s!true\fi\else\s!false\fi}
% check macros
@@ -141,8 +143,8 @@
\newconditional\c_checked_mode
\def\syst_modes_check_indeed#1%
- {\ifcsname\s!mode#1\endcsname
- \ifcase\csname\s!mode#1\endcsname\else
+ {\ifcsname\??mode#1\endcsname
+ \ifcase\csname\??mode#1\endcsname\else
\let\syst_modes_check_step\gobbleoneargument
\fi
\fi}
@@ -157,8 +159,8 @@
\fi}
\def\syst_modes_check_all_indeed#1%
- {\ifcsname\s!mode#1\endcsname
- \ifcase\csname\s!mode#1\endcsname
+ {\ifcsname\??mode#1\endcsname
+ \ifcase\csname\??mode#1\endcsname
\let\syst_modes_check_all_step\gobbleoneargument
\fi
\else
@@ -198,25 +200,25 @@
%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}%
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \expandafter\edef\csname\??modestack#1\endcsname{\number\csname\??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
+ \csname\??mode#1\endcsname\csname\??modestack#1\endcsname\relax
\fi}
\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}%
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \expandafter\edef\csname\??modestack\systemmodeprefix#1\endcsname{\number\csname\??mode\systemmodeprefix#1\endcsname}%
\expandafter\pushmacro\csname\??modestack\systemmodeprefix#1\endcsname}
\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
+ \csname\??mode\systemmodeprefix#1\endcsname\csname\??modestack\systemmodeprefix#1\endcsname\relax
\fi}
%D Here is a relatively new variant of mode checking:
@@ -625,4 +627,51 @@
\def\env {\getvariable \s!environment}
\def\envvar {\getvariabledefault\s!environment}
+%D \macros
+%D {defineselector,setupselector,select,directselect}
+%D
+%D \starttyping
+%D \defineselector[caption][max=2,n=2]
+%D
+%D \start
+%D \setupselector[caption][n=1]
+%D \placelist[figure][criterium=all]
+%D \stop
+%D
+%D \starttext
+%D \placefigure
+%D {\select{caption}{zapf}{\input zapf \relax}}
+%D {}
+%D \stoptext
+%D \stoptyping
+
+\installcorenamespace{selector}
+
+\unexpanded\def\defineselector{\dodoubleargument\syst_selectors_define}
+\unexpanded\def\setupselector {\dodoubleargument\syst_selectors_setup}
+
+% \def\syst_selectors_define[#1][#2]{\getparameters[\??selector#1][\c!max=\plusone,\c!n=\plusone,#2]}
+% \def\syst_selectors_setup [#1][#2]{\getparameters[\??selector#1][#2]}
+
+\def\syst_selectors_define[#1][{\getparameters[\??selector#1][\c!max=\plustwo,\c!n=\plusone,}
+\def\syst_selectors_setup [#1][{\getparameters[\??selector#1][}
+
+\unexpanded\def\select % unexpandable
+ {\directselect}
+
+% \def\directselect#1% expandable
+% {\filterfromnext % maybe add an \expanded
+% {\csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\endcsname}%
+% {\csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}}
+%
+% this is more efficient when the arguments are used a few times (or passed along):
+
+\def\directselect#1% expandable
+ {\expandafter\filterfromnext
+ \csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\expandafter\endcsname
+ \csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}
+
+\letvalue{\??selector\c!max}\plusone
+\letvalue{\??selector\c!n }\plusone
+
\protect \endinput
diff --git a/tex/context/base/core-fnt.mkiv b/tex/context/base/core-fnt.mkiv
deleted file mode 100644
index 980f1a85c..000000000
--- a/tex/context/base/core-fnt.mkiv
+++ /dev/null
@@ -1,158 +0,0 @@
-%D \module
-%D [ file=core-fnt,
-%D version=1995.10.10,
-%D title=\CONTEXT\ Core Macros,
-%D subtitle=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.
-
-\writestatus{loading}{ConTeXt Core Macros / Fonts}
-
-\unprotect
-
-%D \macros
-%D {compound}
-%D
-%D We will overload the already active \type {|} so we have
-%D to save its meaning in order to be able to use this handy
-%D macro.
-%D
-%D \starttyping
-%D so test\compound{}test can be used instead of test||test
-%D \stoptyping
-
-\bgroup \catcode\barasciicode\activecatcode \gdef\compound#1{|#1|} \egroup
-
-%D Here we hook some code into the clean up mechanism needed
-%D for verbatim data.
-
-\appendtoks
- \disablecompoundcharacters
- \disablediscretionaries
-\to \everycleanupfeatures
-
-%D The following code will me mkiv'd when needed. It's rather easy to
-%D extend the kerner with glue.
-
-%D \macros
-%D {stretched}
-%D
-%D Stretching characters in a word is a sort of typographical
-%D murder. Nevertheless we support this manipulation for use in
-%D for instance titles.
-%D
-%D \starttyping
-%D \hbox to 5cm{\stretched{murder}}
-%D \stoptyping
-%D
-%D \typebuffer
-%D
-%D or
-%D
-%D \startexample
-%D \getbuffer
-%D \stopexample
-%D
-%D \showsetup{stretched}
-
-\unexpanded\def\stretched#1%
- {\ifvmode\hbox to \hsize\else\ifinner\else\hbox\fi\fi
- \bgroup\processtokens\relax\hss\relax{\hss\hss}{#1}\egroup}
-
-%D \startbuffer
-%D \stretched{Unknown Box}
-%D \hbox to .5\hsize{\stretched{A Horizontal Box}}
-%D \vbox to 2cm{\stretched{A Vertical Box}}
-%D \hbox to 3cm{\stretched{sp{\'e}c{\`\i}{\"a}l}}
-%D \stopbuffer
-%D
-%D \getbuffer
-%D
-%D The first line of this macros takes care of boxing. Normally
-%D one will use an \type{\hbox} specification. The last line
-%D shows how special characters should be passed.
-%D
-%D \typebuffer
-
-%D \macros
-%D {stretchednormalcase, stretcheduppercase, stretchedlowercase}
-%D
-%D A convenient alternative is:
-%D
-%D \starttyping
-%D \stretcheduppercase{Is this what you like?}
-%D \stoptyping
-%D
-%D \typebuffer
-%D
-%D this one uses fixed skips and kerns.
-%D
-%D \startexample
-%D \getbuffer
-%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{.@/}
-
-\unexpanded\def\stretchednormalcase
- {\stretchedsomecase\firstofoneargument}
-
-\unexpanded\def\stretcheduppercase
- {\stretchedsomecase{\the\everyuppercase\uppercase}}
-
-\unexpanded\def\stretchedlowercase
- {\stretchedsomecase{\the\everylowercase\lowercase}}
-
-\def\stretchedsomecase#1#2%
- {\bgroup
- #1{\def\textstring{#2}}%
- \ifdim\stretchedspaceamount=\zeropoint
- \textstring
- \else
- \def\textkern##1%
- {% beware: ##1 may not be \box\somebox -)
- \determinemidwordbreak{##1}{\stretchedbreaktokens}%
- \kern\stretchedspaceamount##1\domidwordbreak}%
- \def\textskip
- {\scratchdimen\stretchedspaceamount
- \hskip\stretchedspacefactor\scratchdimen}%
- \@EA\processtokens\@EA\relax\@EA\textkern\@EA\relax\@EA\textskip\@EA{\textstring}%
- \fi
- \egroup}
-
-%D An auxiliary macro, see for usage \type {\stretcheduppercase}.
-
-\let\domidwordbreak\relax
-
-\def\setmidwordbreaktoken#1%
- {\sfcode`#1=5000\relax}
-
-\def\determinemidwordbreak#1#2%
- {\edef\midwordbreaktokens{#2}%
- \ifx\midwordbreaktokens\empty
- \global\let\domidwordbreak\relax
- \else
- \setbox\scratchbox\hbox
- {\expandafter\handletokens\midwordbreaktokens\with\setmidwordbreaktoken
- a\space \!!dimena\lastskip
- #1\space\!!dimenb\lastskip \relax % needed
- \ifdim\!!dimena=\!!dimenb
- \globallet\domidwordbreak\relax
- \else
- \globallet\domidwordbreak\allowbreak
- \fi}%
- \fi}
-
-\protect \endinput
diff --git a/tex/context/base/core-ini.mkiv b/tex/context/base/core-ini.mkiv
index de37bf08f..7b32cb3a2 100644
--- a/tex/context/base/core-ini.mkiv
+++ b/tex/context/base/core-ini.mkiv
@@ -13,67 +13,199 @@
\writestatus{loading}{ConTeXt Core Macros / Additional Initialization}
-%D We will move more code to here, so that we become less dependent of the
-%D orde in which modules are loaded.
-
\unprotect
-\everypar \emptytoks
-\neverypar \emptytoks
+%D We introduce a couple of variables that are used all over \CONTEXT. Alternatively
+%D we could define them in each module but as they are part of the bigger picture we
+%D prefer to do it here. Ideally we should hav ea proper dependency tree but it might
+%D be that we want to make versions with a smaller footprints in which case one would
+%D still need to define the token list registers (unless we could do that runtime).
-\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
+%D \macros
+%D {every...}
+%D
+%D A few every's.
-\appendtoks
- \flushpostponedbookmark
-\to \neverypar
+%D Output routine:
-\appendtoks
- \flushpostponedbookmark
-\to \everylistentry
+\newtoks \everybeforeoutput
+\newtoks \everyafteroutput
-\appendtoks
- \flushnotes
-\to \everydisplay
+%D Shipout:
+
+\newtoks \everyshipout
+\newtoks \everybeforeshipout
+\newtoks \everyaftershipout
+\newtoks \everyfirstshipout
+\newtoks \everylastshipout
+
+%D End of run:
+
+\newtoks \everybye
+\newtoks \everygoodbye
+\newtoks \everynotabene
+
+%D Document:
+
+\newtoks \everysetupdocument
+\newtoks \everyendoftextbody
+
+\newtoks \everystarttext
+\newtoks \everystoptext
+
+%D Purity:
+
+\newtoks \everyforgetall
+\newtoks \everycleanupfeatures
+\newtoks \everysimplifycommands
+
+\let\simplifiedcommands\everysimplifycommands % backward compatible, will stay as it's used in styles
+
+\unexpanded\def\forgetall {\the\everyforgetall}
+\unexpanded\def\cleanupfeatures {\the\everycleanupfeatures}
+\unexpanded\def\simplifycommands{\the\everysimplifycommands}
\appendtoks
- \adjustsidefloatdisplaylines
-\to \everydisplay
+ \everypar\emptytoks % pretty important
+\to \everyforgetall
+
+%D Page building:
+
+\newtoks \everybeforepagebody
+\newtoks \everyafterpagebody
+
+\let\everypagebody\everybeforepagebody % backward compatible, will become obsolete
+
+%D Floats:
+
+\newtoks \everyinsidefloat
+
+%D Sectioning:
+
+\newtoks \everyheadstart
+
+%D Par building (experimental, used in xml <p> .. </p>)
+
+\newtoks \everybeginofpar
+\newtoks \everyendofpar
+%newtoks \everyparflush
+
+\unexpanded\def\bpar{\the\everybeginofpar\ignorespaces} % may interfere with \everypar
+\unexpanded\def\epar{\ifhmode\removeunwantedspaces\the\everyendofpar\fi} % test prevents problems with \bpar\epar
+
+%D Lists:
+
+\newtoks \everylistentry
+\newtoks \everysavesortkeys
+
+%D Marks:
-% \appendtoks
-% \flushsyncpositions
-% \to \everyheadstart
+\newtoks \everymarking
-% \appendtoks
-% \flushsyncresets
-% \to \everyendoftextbody
+%D Fonts:
+
+\newtoks \everyfont
+\newtoks \everyglobalbodyfont
+\newtoks \everydefinedfont
+
+\newevery \everybodyfont \EveryBodyFont
+\newevery \everyfontswitch \EveryFontSwitch
+
+\newtoks \everysetupbodyfont
+\newtoks \everyswitchtobodyfont
+
+%D Math:
+
+\newtoks \everybeforedisplayformula
+\newtoks \everymathematics
+
+\prependtoks \the\everymathematics \to \everymath
+\prependtoks \the\everymathematics \to \everydisplay
+
+%D Tables:
+
+\newtoks \everytable % we need to disstinguish kinds
+
+%D State mess:
+
+\newtoks \everypushsomestate
+\newtoks \everypopsomestate
+
+\unexpanded\def\pushsomestates{\the\everypushsomestate}
+\unexpanded\def\popsomestates {\the\everypopsomestate }
+
+%D More generic (used to be pushcolor etc)
+
+\newtoks\everystarttextproperties
+\newtoks\everystoptextproperties
+
+\unexpanded\def\starttextproperties{\the\everystarttextproperties}
+\unexpanded\def\stoptextproperties {\the\everystoptextproperties}
+
+%D \macros
+%D {trialtypesetting}
+%D
+%D We disable trial typesetting in the output routine,
+%D just to be sure.
+
+\prependtoks
+ \resettrialtypesetting
+\to \everybeforepagebody
+
+%D \macros
+%D {ifinpagebody,ifinsidecolumns,ifdoublesided,ifsinglesided}
+%D
+%D These will become system modes and conditionals
+
+\newif \ifinpagebody
+\newif \ifinsidecolumns
+\newif \ifdoublesided \doublesidedfalse
+\newif \ifsinglesided \singlesidedtrue
+\newif \ifinsidefloat
+\newif \ifdoingblocks
+\newif \ifgridsnapping
+
+%D \macros
+%D {ifproductionrun}
+%D
+%D This boolean can be used to bypass certain initializations.
+
+\newif\ifproductionrun
\appendtoks
- \ignorespaces
-\to \everybeginofpar
+ \productionruntrue
+\to \everydump
+
+%D \macros
+%D {everyboxedcontent, ifboxedcontent,
+%D startboxedcontent, stopboxedcontent}
+%D
+%D This one is relatively new and will be used as a more robust test for inner
+%D situations.
+
+\newif \ifboxedcontent
+\newtoks\everyboxedcontent
\appendtoks
- \removeunwantedspaces
- %strut % option ?
- % \flushsyncresets
- %setlastlinewidth % gone, will be done in lua
- \endgraf
-\to \everyendofpar
+ \boxedcontenttrue
+\to \everyboxedcontent
+
+\unexpanded\def\startboxedcontent{\bgroup\the\everyboxedcontent}
+
+\let\stopboxedcontent\egroup
+
+%D We store some original meanings, maybe in \type {math-ini}.
+
+\let\normalat \at
+\let\normalin \in
+\let\normalfrom \from
+%let\normalover \over
+\let\normalabout\about
+
+%D This will be implemented way later:
+
+\let\setlayoutcomponentattribute \gobbleoneargument
+\let\resetlayoutcomponentattribute\relax
+\let\layoutcomponentboxattribute \empty
\protect \endinput
diff --git a/tex/context/base/core-mis.mkiv b/tex/context/base/core-mis.mkiv
deleted file mode 100644
index 5c364f3c4..000000000
--- a/tex/context/base/core-mis.mkiv
+++ /dev/null
@@ -1,738 +0,0 @@
-%D \module
-%D [ file=core-mis,
-%D version=1998.01.29,
-%D title=\CONTEXT\ Core Macros,
-%D subtitle=Miscelaneous,
-%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 / Misc Commands}
-
-% needs to be redone
-
-\unprotect
-
-%D Sometimes (for instance in bookmarks) we need to simplify macro
-%D behaviour, so here is the hook.
-
-\ifx\simplifiedcommands\undefined \newtoks\simplifiedcommands \fi
-
-\def\simplifycommands{\the\simplifiedcommands}
-
-%D A possibly growing list:
-
-%appendtoks \def\executesynonym#1#2#3#4{#3}\to\simplifiedcommands
-%appendtoks \def\executesort#1#2#3{#3}\to\simplifiedcommands
-
-\appendtoks \def\ { }\to\simplifiedcommands
-\appendtoks \def\type#1{\letterbackslash\checkedstrippedcsname#1}\to\simplifiedcommands
-\appendtoks \def\tex#1{\letterbackslash#1}\to\simplifiedcommands
-\appendtoks \def\TeX{TeX}\to\simplifiedcommands
-\appendtoks \def\ConTeXt{ConTeXt}\to\simplifiedcommands
-\appendtoks \def\MetaPost{MetaPost}\to\simplifiedcommands
-\appendtoks \def\MetaFont{MetaFont}\to\simplifiedcommands
-\appendtoks \def\MetaFun{MetaFun}\to\simplifiedcommands
-%appendtoks \def||{-}\to\simplifiedcommands
-\appendtoks \def|#1|{\ifx#1\empty\empty-\else#1\fi}\to\simplifiedcommands
-
-\appendtoks\let\buildtextaccent\secondoftwoarguments\to\simplifiedcommands
-
-% THIS WAS MAIN-002.TEX
-
-\def\horitems#1#2% #1=breedte #2=commandos
- {\scratchdimen#1%
- \divide\scratchdimen \nofitems
- \!!counta\zerocount
- \def\docommand##1%
- {\advance\!!counta \plusone
- \processaction
- [\@@isalign]
- [ \v!left=>\hbox to \scratchdimen{\strut##1\hss},
- \v!right=>\hbox to \scratchdimen{\hss\strut##1},
- \v!middle=>\hbox to \scratchdimen{\hss\strut##1\hss},
- \v!margin=>\ifnum\!!counta=\plusone\hss\else\hfill\fi
- \strut##1%
- \ifnum\!!counta=\nofitems\hss\else\hfill\fi,
- \s!default=>\hbox to \scratchdimen{\hss\strut##1\hss}, % midden
- \s!unknown=>\hbox to \scratchdimen{\strut##1\hss}]}% % links
- \hbox to #1{\hss#2\hss}}
-
-\def\veritems#1#2% #1=breedte #2=commandos
- {\scratchdimen#1%
- \def\docommand##1%
- {\ifdim\scratchdimen<\zeropoint % the - was a signal
- \hbox to -\scratchdimen{\hss\strut##1}%
- \else\ifdim\scratchdimen>\zeropoint
- \hbox to \scratchdimen{\strut##1\hss}%
- \else
- \hbox{\strut##1}%
- \fi\fi}%
- \vbox{#2}}
-
-\def\dosetupitems[#1]%
- {\getparameters[\??is][#1]%
- \doif\@@iswidth\v!unknown
- {\def\@@iswidth{\hsize}}%
- \doifconversiondefinedelse\@@issymbol
- {\def\doitembullet##1{\convertnumber{\@@issymbol}{##1}}}
- {\doifsymboldefinedelse\@@issymbol
- {\def\doitembullet##1{\symbol[\@@issymbol]}}{}}}
-
-\def\makeitemsandbullets#1%
- {\doifelse\@@isn\v!unknown
- {\getcommalistsize[#1]%
- \edef\nofitems{\commalistsize}}
- {\edef\nofitems{\@@isn}}%
- \setbox0\hbox
- {\doitems \@@iswidth
- {\processcommalist[#1]\docommand}}%
- \setbox2\hbox
- {\doitems \@@isbulletbreedte
- {\dorecurse\nofitems
- {\docommand{\strut\doitembullet\recurselevel}}}}}
-
-\def\dostartitems#1#2#3%
- {\let\doitems#2%
- \def\@@isbulletbreedte{#3}%
- \makeitemsandbullets{#1}%
- \@@isbefore}
-
-\def\dostopitems
- {\@@isafter
- \egroup}
-
-\setvalue{doitems\v!top}#1%
- {\dostartitems{#1}\horitems\@@iswidth
- \noindent\vbox
- {\forgetall
- \doifsomething\@@issymbol
- {\doifnot\@@issymbol\v!none
- {\box2
- \@@isinbetween
- \nointerlineskip}}%
- \box0}%
- \dostopitems}
-
-\setvalue{doitems\v!bottom}#1%
- {\dostartitems{#1}\horitems\@@iswidth
- \noindent\vbox
- {\forgetall
- \box0
- \doifsomething\@@issymbol
- {\@@isinbetween
- \nointerlineskip
- \box2}}%
- \dostopitems}
-
-\setvalue{doitems\v!inmargin}#1%
- {\dostartitems{#1}\veritems{-1.5em}% - is a signal
- \noindent\hbox{\llap{\box2\hskip\leftmargindistance}\box0}%
- \dostopitems}
-
-\setvalue{doitems\v!left}#1%
- {\advance\hsize -1.5em%
- \dostartitems{#1}\veritems{1.5em}%
- \noindent\hbox{\box2\box0}%
- \dostopitems}
-
-\setvalue{doitems\v!right}#1%
- {\dostartitems{#1}\veritems{0em}%
- \noindent\hbox{\box0\hskip-\wd2\box2}%
- \dostopitems}
-
-\unexpanded\def\setupitems
- {\dosingleargument\dosetupitems}
-
-\def\complexitems[#1]%
- {\bgroup
- \setupitems[#1]%
- \parindent\zeropoint
- \setlocalhsize
- \hsize\localhsize
- \dontcomplain
- \executeifdefined{doitems\@@islocation}{\getvalue{doitems\v!left}}}
-
-\definecomplexorsimpleempty\items
-
-\setupitems
- [\c!location=\v!left,
- \c!symbol=5,
- \c!width=\hsize,
- \c!align=\v!middle,
- \c!n=\v!unknown,
- \c!before=\blank,
- \c!inbetween={\blank[\v!medium]},
- \c!after=\blank]
-
-% there is quite some historic balast in this mechanism, the next variant
-% is a first cleanup
-
-\let\currentparagraph\empty
-
-\newcount\alcounter \newcount\alnsize \newdimen\alhsize
-
-\def\paragraphparameter#1% \checkedparameter\??al\currentparagraph#1
- {\executeifdefined{\??al\currentparagraph#1}{\executeifdefined{\??al#1}\empty}}
-
-\def\paragraphcellmeter#1#2% \checkedparameter\??al\currentparagraph#1
- {\executeifdefined{\??al\currentparagraph\number#1#2}{\paragraphparameter{#2}}}
-
-\def\dodefineparagraphs[#1][#2]%
- {\edef\currentparagraph{#1}%
- \setvalue{\s!do\s!next\currentparagraph}%
- {\def\\{\getvalue\currentparagraph}}%
- \setvalue\currentparagraph
- {\getvalue{\s!do\s!next#1}%
- \dostartparagraphs{#1}}%
- \setvalue{\e!next\currentparagraph}%
- {\getvalue{#1}}%
- \setvalue{\e!start\currentparagraph}%
- {\bgroup
- \edef\currentparagraph{#1}%
- \letvalueempty{\s!do\s!next\currentparagraph}%
- \setvalue{\e!stop\currentparagraph}{\getvalue\currentparagraph\egroup}%
- \getvalue\currentparagraph}%
- \getparameters[\??al\currentparagraph]%
- [%\c!n=3,
- %\c!before=\blank,
- %\c!after=\blank,
- %\c!distance=1em,
- %\c!height=\v!fit,
- %\c!rule=\v!off,
- %\c!command=,
- %\c!align=,
- %\c!tolerance=\v!tolerant,
- %\c!rulethickness=\linewidth,
- %\c!rulecolor=,
- %\c!style=,
- %\c!color=,
- %\c!top=,
- %\c!top=\vss,
- %\c!bottom=\vfill,
- #2]%
- \setvalue{\e!setup#1\e!endsetup}%
- {\setupparagraphs[#1]}%
- \dorecurse
- {\paragraphparameter\c!n}
- {\setupparagraphs
- [\currentparagraph]
- [\recurselevel]
- [\c!width=,
- %\c!bottom=\paragraphparameter\c!bottom,
- %\c!top=\paragraphparameter\c!top,
- %\c!height=\paragraphparameter\c!height,
- %\c!rule=\paragraphparameter\c!rule,
- %\c!rulethickness=\paragraphparameter\c!rulethickness,
- %\c!rulecolor=\paragraphparameter\c!rulecolor,
- %\c!align=\paragraphparameter\c!align,
- %\c!tolerance=\paragraphparameter\c!tolerance, % obsolete
- %\c!distance=\paragraphparameter\c!distance,
- \c!style=\paragraphparameter\c!style,
- \c!color=\paragraphparameter\c!color]}%
- \setupparagraphs[\currentparagraph][1][\c!distance=\zeropoint]}
-
-\unexpanded\def\defineparagraphs
- {\dodoubleargument\dodefineparagraphs}
-
-\def\dosetupparagraphs[#1][#2][#3]%
- {\edef\currentparagraph{#1}%
- \ifsecondargument
- \doifelse{#2}\v!each
- {\dorecurse
- {\paragraphparameter\c!n}
- {\getparameters[\??al\currentparagraph\recurselevel][#3]}}
- {\doifelsenothing{#3}
- {\getparameters[\??al\currentparagraph][#2]}
- {\def\docommand##1{\getparameters[\??al\currentparagraph##1][#3]}%
- \processcommalist[#2]\docommand}}%
- \else
- \getparameters[\??al][#1]%
- \fi}
-
-\unexpanded\def\setupparagraphs
- {\dotripleempty\dosetupparagraphs}
-
-\setupparagraphs
- [\c!n=3,
- \c!before=\blank,
- \c!after=\blank,
- \c!distance=1em,
- \c!height=\v!fit,
- \c!rule=\v!off,
- \c!command=,
- \c!align=,
- \c!tolerance=\v!tolerant, % obsolete
- \c!rulethickness=\linewidth,
- \c!rulecolor=,
- \c!style=,
- \c!color=,
- \c!top=,
- \c!top=\vss,
- \c!bottom=\vfill]
-
-\def\doparagraphrule
- {\doifelse{\paragraphcellmeter\alcounter\c!rule}\v!on
- {\linewidth\paragraphcellmeter\alcounter\c!rulethickness
- \scratchdimen\dimexpr(\paragraphcellmeter\alcounter\c!distance-\linewidth)/2\relax
- \hskip\scratchdimen
- \color[\paragraphcellmeter\alcounter\c!rulecolor]{\vrule\!!width\linewidth}%
- \hskip\scratchdimen}
- {\hskip\paragraphcellmeter\alcounter\c!distance}}
-
-\def\dostartparagraph
- {\doifelsenothing{\paragraphcellmeter\alcounter\c!width}
- {\!!widtha\alhsize
- \divide\!!widtha \alnsize}
- {\!!widtha\paragraphcellmeter\alcounter\c!width}%
- \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}%
- \bgroup
- \blank[\v!disable]%
- \forgetall
- \paragraphcellmeter\alcounter\c!top
- \paragraphparameter\c!inner
- \hsize\!!widtha % setting \wd afterwards removed
- \paragraphcellmeter\alcounter\c!inner % twice
- \expanded{\setupalign [\paragraphcellmeter\alcounter\c!align ]}% {normal,verytolerant,stretch}
- \expanded{\setuptolerance[\paragraphcellmeter\alcounter\c!tolerance]}% obsolete
- \ignorespaces
- \endgraf
- \ignorespaces
- %
- % Nadeel van de onderstaande constructie is dat \everypar
- % binnen een groep kan staan en zo steeds \begstruts
- % worden geplaatst. Mooi is anders dus moet het anders!
- %
- % Hier is \Everypar niet nodig.
- %
- \everypar{\begstrut\everypar\emptytoks}%
- %
- \nospace % remove + ignore
- \paragraphcellmeter\alcounter\c!command}
-
-\def\dostopparagraph
- {\ifvmode
- \removelastskip
- \else
- \unskip\endstrut\endgraf
- \fi
- \paragraphcellmeter\alcounter\c!bottom
- \egroup
- \ifdim\wd\scratchbox=\zeropoint % no data
- \wd\scratchbox\!!widtha
- \fi
- \box\scratchbox
- \endgroup
- \ifnum\alcounter<\paragraphparameter\c!n\relax
- \@EA\doparagraphcell
- \else
- \@EA\dostopparagraphs
- \fi}
-
-\def\doparagraphcell
- {\global\advance\alcounter \plusone
- \doifelsenothing{\paragraphcellmeter\alcounter\c!distance}
- {\ifnum\alcounter=\plusone\else
- \hskip\paragraphparameter\c!distance
- \fi}
- {\ifnum\alcounter=\plusone
- \hskip\paragraphcellmeter\alcounter\c!distance
- \else
- \doparagraphrule
- \fi}%
- \letvalue\currentparagraph\dostopparagraph
- \dostartparagraph}
-
-\def\dostartparagraphs#1%
- {\bgroup
- \edef\currentparagraph{#1}%
- \global\alcounter\zerocount
- \parindent\zeropoint
- \setlocalhsize
- \alhsize\localhsize
- \alnsize\paragraphparameter\c!n\relax
- \dorecurse \alnsize
- {\doifelsenothing{\paragraphcellmeter\recurselevel\c!distance}
- {\ifnum\recurselevel=\plusone\else
- \global\advance\alhsize -\paragraphparameter\c!distance
- \fi}
- {\global\advance\alhsize -\paragraphcellmeter\recurselevel\c!distance}%
- \doifsomething{\paragraphcellmeter\recurselevel\c!width}
- {\global\advance\alnsize \minusone
- \global\advance\alhsize -\paragraphcellmeter\recurselevel\c!width}}%
- %whitespace % gaat fout bij \framed
- \paragraphparameter\c!before
- \leavevmode % gaat wel goed bij \framed, brrr
- \setbox\scratchbox\vbox\bgroup\hbox\bgroup\doparagraphcell}
-
-\def\dostopparagraphs
- {\egroup
- \egroup
- \iftrue
- \hbox{\raise\strutheight\box\scratchbox}% new
- \else
- \box\scratchbox % old
- \fi
- \par
- \paragraphparameter\c!after
- \egroup}
-
-% Is this used at all?
-
-\def\dosetuptab[#1]%
- {\getparameters[\??ta]
- [\c!headstyle=\v!normal,
- \c!headcolor=,
- \c!style=\v!normal,
- \c!color=,
- \c!width=\v!broad,
- \c!sample={\hskip4em},
- \c!before=,
- \c!after=,
- #1]%
- \definedescription
- [tab]
- [\c!headstyle=\@@taheadstyle,
- \c!headcolor=\@@tacolor,
- \c!sample=\@@tasample,
- \c!width=\@@tawidth,
- \c!before=\@@tabefore,
- \c!after=\@@taafter]}
-
-\unexpanded\def\setuptab
- {\dosingleargument\dosetuptab}
-
-\setuptab
- [\c!location=\v!left]
-
-% seldom used, move from kernel to run time module
-
-\ifx\tfx\undefined \let\tfx\relax \fi
-
-\def\basegrid
- {\dosingleempty\dobasegrid}
-
-\def\dobasegrid[#1]%
- {\begingroup
- \getparameters[\??rt]
- [\c!x=0,\c!y=0,
- \c!nx=10,\c!ny=10,
- \c!dx=.5,\c!dy=.5,
- \c!xstep=0,\c!ystep=0,
- \c!unit=\s!cm,
- \c!scale=1,
- \c!factor=1,
- \c!offset=\v!yes,
- \c!location=\v!left,
- #1]%
- \startpositioning
- \dimen0=\@@rtdx\@@rtunit\relax
- \dimen0=\@@rtscale\dimen0\relax
- \dimen0=\@@rtfactor\dimen0\relax
- \multiply\dimen0 \@@rtnx\relax
- \dimen2=\@@rtdy\@@rtunit\relax
- \dimen2=\@@rtscale\dimen2\relax
- \dimen2=\@@rtfactor\dimen2\relax
- \multiply\dimen2 \@@rtny\relax
- \def\horline
- {\vbox
- {\hrule
- \!!width \dimen0
- \!!height \linewidth
- \!!depth \!!zeropoint}}%
- \def\verline%
- {\vrule
- \!!width \linewidth
- \!!height \dimen2
- \!!depth \!!zeropoint}%
- \doglobal\newcounter\@@gridc
- \doglobal\newcounter\@@gridd
- \doglobal\newcounter\@@gride
- \def\setlegend##1##2##3%
- {\gdef\@@gridc{0}%
- \dimen0=2em\relax
- \dimen2=##2\@@rtunit\relax
- \dimen2=\@@rtscale\dimen2\relax
- \dimen2=\@@rtfactor\dimen2\relax
- \divide\dimen0 \dimen2\relax
- \xdef\@@gride{\number\dimen0}%
- \ifnum\@@gride>50
- \gdef\@@gride{100}%
- \else\ifnum\@@gride>10
- \gdef\@@gride{50}%
- \else\ifnum\@@gride>5
- \gdef\@@gride{10}%
- \else\ifnum\@@gride>1
- \gdef\@@gride{5}%
- \else
- \gdef\@@gride{1}%
- \fi\fi\fi\fi
- \gdef\@@gridd{0}%
- \def\legend
- {\ifnum\@@gridd=\zerocount
- \vbox
- {\increment(\@@gridc,##1)%
- \hbox to 2em{\hss\@@gridc\hss}}%
- \global\let\@@gridd=\@@gride
- \fi
- \doglobal\decrement\@@gridd
- \doglobal\increment(\@@gridc,##1)}}%
- \def\draw##1##2##3##4##5##6##7##8##9%
- {\setuppositioning
- [\c!state=##8,
- \c!xstep=\v!absolute,
- \c!ystep=\v!absolute,
- \c!unit=\@@rtunit,
- \c!scale=\@@rtscale,
- \c!factor=\@@rtfactor,
- \c!offset=\@@rtoffset,
- \c!xoffset=##6,
- \c!yoffset=##7]%
- \doifelse{##9}\v!middle
- {\scratchdimen##3pt\scratchdimen.5\scratchdimen
- \edef\@@psxx{\withoutpt\the\scratchdimen}%
- \scratchdimen##4pt\scratchdimen.5\scratchdimen
- \edef\@@psyy{\withoutpt\the\scratchdimen}%
- \scratchcounter##2\advance\scratchcounter -1
- \edef\@@pszz{\the\scratchcounter}}
- {\edef\@@psxx{0}\edef\@@psyy{0}\edef\@@pszz{##2}}%
- \position(\@@psxx,\@@psyy){##1}%
- \setuppositioning
- [\c!state=##8,
- \c!xstep=\v!relative,
- \c!ystep=\v!relative,
- \c!scale=\@@rtscale,
- \c!factor=\@@rtfactor,
- \c!offset=\@@rtoffset,
- \c!unit=\@@rtunit]%
- \dorecurse\@@pszz{\position(##3,##4){##5}}}%
- \draw
- \verline\@@rtnx\@@rtdx0\verline\!!zeropoint\!!zeropoint\v!start\empty
- \draw
- \horline\@@rtny0\@@rtdy\horline\!!zeropoint\!!zeropoint\v!start\empty
- \tfx
- \doifnot\@@rtxstep{0}
- {\setlegend\@@rtxstep\@@rtdx\@@rtx
- \draw\legend\@@rtnx\@@rtdx0\legend{-1em}{-1.5em}\v!overlay\@@rtlocation}%
- \doifnot\@@rtystep{0}
- {\setlegend\@@rtystep\@@rtdy\@@rty
- \draw\legend\@@rtny0\@@rtdy\legend{-2em}{-.75ex}\v!overlay\@@rtlocation}%
- \stoppositioning
- \endgroup}
-
-\let\grid\basegrid
-
-\definetabulate
- [\v!legend]
- [|emj1|i1|mR|]
-
-\setuptabulate
- [\v!legend]
- [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}]
-
-\definetabulate
- [\v!legend][\v!two]
- [|emj1|emk1|i1|mR|]
-
-\definetabulate
- [\v!fact]
- [|R|ecmj1|i1mR|]
-
-\setuptabulate
- [\v!fact]
- [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}]
-
-\unexpanded\def\xbox
- {\bgroup\aftergroup\egroup\hbox\bgroup\tx\let\next=}
-
-\unexpanded\def\xxbox
- {\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=}
-
-%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%
-%D {\hbox{\high{\tx#1\kern-.25em}/\low{\kern-.25em\tx#2}}}
-%D
-%D test \vfrac{1}{2} test \vfrac{123}{456} test
-%D \stopbuffer
-%D
-%D \typebuffer {\showmakeup\getbuffer}
-%D
-%D A better way to handle the kerning is the following, here
-%D we kind of assume that tye slash is symmetrical and has
-%D nearly zero width.
-%D
-%D \startbuffer
-%D \def\vfract#1#2%
-%D {\hbox{\high{\tx#1}\hbox to \zeropoint{\hss/\hss}\low{\tx#2}}}
-%D \stopbuffer
-%D
-%D \typebuffer {\showmakeup\getbuffer}
-%D
-%D The third and best alternative is the following:
-%D
-%D {\showmakeup\getbuffer}\crlf\getbuffer
-%D
-%D This time we measure the height of the \type {/} and
-%D shift over the maximum height and depths of this
-%D character and the fractional digits (we use 57 as
-%D sample). Here we combine all methods in one macros.
-
-\setnewconstant\vulgarfractionmethod\plusthree
-
-\definehspace[vulgarfraction][.25em] % [.15em]
-\definesymbol[vulgarfraction][/] % [\raise.2ex\hbox{/}]
-
-\unexpanded\def\vulgarfraction#1#2%
- {\dontleavehmode
- \hbox
- {\def\vulgarfraction{vulgarfraction}%
- \ifcase\vulgarfractionmethod
- #1\symbol[\vulgarfraction]#2%
- \or
- \high{\tx#1\kern-\hspaceamount\empty\vulgarfraction}%
- \symbol[\vulgarfraction]%
- \low {\kern-\hspaceamount\empty\vulgarfraction\tx#2}%
- \or
- \high{\tx#1}%
- \hbox to \zeropoint{\hss\symbol[\vulgarfraction]\hss}%
- \low{\tx#2}%
- \or
- \setbox0\hbox{\symbol[\vulgarfraction]}%
- \setbox2\hbox{\txx57}%
- \raise\ht0\hbox{\lower\ht2\hbox{\txx#1}}%
- \hbox to \zeropoint{\hss\symbol[\vulgarfraction]\hss}%
- \lower\dp0\hbox{\raise\dp2\hbox{\txx#2}}%
- \fi}}
-
-\ifdefined\vfrac \else \let\vfrac\vulgarfraction \fi
-
-%D \starttabulate
-%D \HL
-%D \NC \bf method \NC \bf visualization \NC\NR
-%D \HL
-%D \NC 0 \NC \vulgarfractionmethod0 \vulgarfraction{1}{2} \NC\NR
-%D \NC 1 \NC \vulgarfractionmethod1 \vulgarfraction{1}{2} \NC\NR
-%D \NC 2 \NC \vulgarfractionmethod2 \vulgarfraction{1}{2} \NC\NR
-%D \NC 3 \NC \vulgarfractionmethod3 \vulgarfraction{1}{2} \NC\NR
-%D \HL
-%D \stoptabulate
-
-%D Under construction:
-%D
-%D \starttyping
-%D \commalistsentence[aap,noot,mies]
-%D \commalistsentence[aap,noot]
-%D \commalistsentence[aap]
-%D \commalistsentence[a,b,c]
-%D \commalistsentence[a,b,c][{ \& },{ and }]
-%D \commalistsentence[a,b,c][+,-]
-%D \stoptyping
-
-% obsolete .. use lua instead
-
-\let\handlecommalistsentence\firstofoneargument
-
-\def\commalistsentenceone{and-1}
-\def\commalistsentencetwo{and-2}
-
-\def\commalistsentence
- {\dodoubleempty\docommalistsentence}
-
-\def\docommalistsentence[#1][#2]%
- {\bgroup
- \getfromcommalist[#2][1]%
- \ifx\commalistelement\empty
- \def\@@commalistsentenceone{\labeltext\commalistsentenceone}%
- \else
- \let\@@commalistsentenceone\commalistelement
- \fi
- \getfromcommalist[#2][2]%
- \ifx\commalistelement\empty
- \def\@@commalistsentencetwo{\labeltext\commalistsentencetwo}%
- \else
- \let\@@commalistsentencetwo\commalistelement
- \fi
- \getcommalistsize[#1]%
- \ifcase\commalistsize\relax
- \def\serializedcommalist{#1}%
- \else
- \let\serializedcommalist\empty
- \scratchcounter\zerocount
- \def\docommand##1%
- {\advance\scratchcounter \plusone
- \ifnum\scratchcounter=\plusone
- \scratchtoks{\handlecommalistsentence{##1}}%
- \else
- \ifnum\scratchcounter=\commalistsize
- \appendtoks\@@commalistsentencetwo\handlecommalistsentence{##1}\to\scratchtoks
- \else
- \appendtoks\@@commalistsentenceone\handlecommalistsentence{##1}\to\scratchtoks
- \fi
- \fi}%
- \processcommacommand[#1]\docommand
- \edef\serializedcommalist{\the\scratchtoks}%
- \fi
- \serializedcommalist
- \egroup}
-
-\def\commacommandsentence[#1]{\@EA\commalistsentence\@EA[#1]}
-
-\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}
-%D
-%D This macro can be used to create tabs:
-%D
-%D \starttyping
-%D \setupheadertexts[{\somekindoftab[alternative=horizontal]{\framed{\realfolio}}}]
-%D \setuptexttexts [{\somekindoftab[alternative=vertical] {\framed{\realfolio}}}]
-%D
-%D \starttext
-%D \showframe \dorecurse{10}{test\page}
-%D \stoptext
-%D \stoptyping
-
-\def\somekindoftab
- {\dosingleempty\dosomekindoftab}
-
-\def\dosomekindoftab[#1]%
- {\bgroup
- \getparameters[xx]
- [\c!alternative=\v!vertical,
- \c!width=\textwidth,\c!height=\textheight,
- \c!n=\lastpage,\c!m=\realpageno,
- #1]%
- \doifelse\xxalternative\v!vertical
- {\dodosomekindoftab\vbox\vskip\xxheight}
- {\dodosomekindoftab\hbox\hskip\xxwidth }}
-
-\def\dodosomekindoftab#1#2#3#4%
- {#1 to #3 \bgroup
- \forgetall
- \ifnum\xxm>\plusone
- #2\zeropoint \!!plus \the\numexpr\xxm -1\relax fill\relax
- \fi
- #4%
- \ifnum\xxm<\xxn\relax
- #2\zeropoint \!!plus \the\numexpr\xxn-\xxm\relax fill\relax
- \fi
- \egroup
- \egroup}
-
-\protect \endinput
diff --git a/tex/context/base/core-sys.lua b/tex/context/base/core-sys.lua
index 0be9fd588..e25c9b8f1 100644
--- a/tex/context/base/core-sys.lua
+++ b/tex/context/base/core-sys.lua
@@ -6,21 +6,93 @@ if not modules then modules = { } end modules ['core-sys'] = {
license = "see context related readme files"
}
-local lower, format = string.lower, string.format
-local extname, basename, removesuffix = file.extname, file.basename, file.removesuffix
+local lower, format, gsub = string.lower, string.format, string.gsub
+local suffixonly, basename, removesuffix = file.suffix, file.basename, file.removesuffix
local environment = environment
-function commands.updatefilenames(inputfilename,outputfilename)
- environment.inputfilename = inputfilename or ""
- environment.outputfilename = outputfilename or ""
- environment.jobfilename = inputfilename or tex.jobname or ""
- environment.jobfilesuffix = lower(extname(environment.jobfilename))
+local report_files = logs.reporter("system","files")
+
+-- function commands.updatefilenames(jobname,fulljobname,inputfilename,outputfilename)
+-- --
+-- environment.jobname = jobname
+-- --
+-- local jobfilename = gsub(fulljobname or jobname or inputfilename or tex.jobname or "","%./","")
+-- --
+-- environment.jobfilename = jobfilename
+-- environment.jobfilesuffix = lower(suffixonly(environment.jobfilename))
+-- --
+-- local inputfilename = gsub(inputfilename or "","%./","")
+-- environment.inputfilename = inputfilename
+-- environment.inputfilebarename = removesuffix(basename(inputfilename))
+-- --
+-- local inputfilerealsuffix = suffixonly(inputfilename)
+-- environment.inputfilerealsuffix = inputfilerealsuffix
+-- --
+-- local inputfilesuffix = inputfilerealsuffix == "" and "tex" or lower(inputfilerealsuffix)
+-- environment.inputfilesuffix = inputfilesuffix
+-- --
+-- local outputfilename = outputfilename or environment.inputfilebarename or ""
+-- environment.outputfilename = outputfilename
+-- --
+-- local runpath = resolvers.cleanpath(lfs.currentdir())
+-- environment.runpath = runpath
+-- --
+-- statistics.register("running on path", function()
+-- return environment.runpath
+-- end)
+-- --
+-- statistics.register("job file properties", function()
+-- return format("jobname: %s, input: %s, suffix: %s",jobfilename,inputfilename,inputfilesuffix)
+-- end)
+-- --
+-- end
+
+function environment.initializefilenames() -- commands.updatefilenames(jobname,fulljobname,input,result)
+
+ local arguments = environment.arguments
+
+ local jobname = arguments.jobname or tex.jobname
+ local fulljobname = arguments.fulljobname or jobname
+ local inputfilename = arguments.input or fulljobname
+ local outputfilename = arguments.result or removesuffix(jobname)
+
+ local inputfilename = suffixonly(inputfilename) == "tex" and removesuffix(inputfilename) or inputfilename or ""
+
+ local filename = fulljobname
+ local suffix = suffixonly(filename)
+
+ local filename = ctxrunner.resolve(filename) -- in case we're prepped
+
+ local jobfilename = jobname or inputfilename or tex.jobname or ""
+ local inputfilename = inputfilename or ""
+
+ jobfilename = gsub(jobfilename, "^./","")
+ inputfilename = gsub(inputfilename,"^./","")
+
+ environment.jobfilename = jobfilename
+ environment.jobfilesuffix = lower(suffixonly(jobfilename))
+
+ environment.inputfilename = inputfilename
environment.inputfilebarename = removesuffix(basename(inputfilename))
- environment.inputfilesuffix = lower(extname(inputfilename))
+ environment.inputfilesuffix = lower(suffixonly(inputfilename))
+
+ environment.outputfilename = outputfilename or environment.inputfilebarename or ""
+
+ environment.filename = filename
+ environment.suffix = suffix
+
+ report_files("jobname: %s, input: %s, result: %s",jobfilename,inputfilename,outputfilename)
+
+ function environment.initializefilenames() end
end
statistics.register("result saved in file", function()
-- suffix will be fetched from backend
- return format( "%s.%s", environment.outputfilename, (tex.pdfoutput>0 and "pdf") or "dvi")
+ local outputfilename = environment.outputfilename or environment.jobname or tex.jobname or "<unset>"
+ if tex.pdfoutput > 0 then
+ return format( "%s.%s, compresslevel %s, objectcompreslevel %s",outputfilename,"pdf",tex.pdfcompresslevel, tex.pdfobjcompresslevel)
+ else
+ return format( "%s.%s",outputfilename,"dvi") -- hard to imagine
+ end
end)
diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv
index 66f2a4380..249500e0a 100644
--- a/tex/context/base/core-sys.mkiv
+++ b/tex/context/base/core-sys.mkiv
@@ -36,21 +36,31 @@
%D line ending. I hate this mess.
\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 ""}}
+
+%D The jobname is what gets loaded by the cont-yes stub file. This name
+%D also determines the name of tuc etc files.
+
+\def \jobfilename {\cldcontext{environment.jobfilename or ""}}
+\def \jobfilesuffix {\cldcontext{environment.jobfilesuffix or ""}}
+
+%D However, that one can itself load another file.
+
+\def \inputfilebarename {\cldcontext{environment.inputfilebarename or ""}}
+\def \inputfilerealsuffix{\cldcontext{environment.inputfilerealsuffix or ""}}
+\def \inputfilesuffix {\cldcontext{environment.inputfilesuffix or ""}}
+\def \inputfilename {\cldcontext{environment.inputfilename or ""}}
+
+%D The output name is only used for some checking.
+
+\def \outputfilename {\cldcontext{environment.outputfilename or ""}}
\installcorenamespace{system}
\installdirectcommandhandler \??system {system}
\appendtoks
- \edef\outputresolution{\directsystemparameter\c!resolution}%
- \edef\outputfilename {\directsystemparameter\c!file }%
- \edef\inputfilename {\directsystemparameter\c!inputfile }%
+% \edef\outputfilename {\directsystemparameter\c!file }%
+% \edef\inputfilename {\directsystemparameter\c!inputfile }%
\to \everysetupsystem
\appendtoks
@@ -75,9 +85,9 @@
\setsystemmode{suffix-\m_system_job_suffix}%
\to \everysetupsystem
-\appendtoks
- \ctxcommand{updatefilenames("\inputfilename","\outputfilename")}%
-\to \everysetupsystem
+% \appendtoks
+% \ctxcommand{updatefilenames("\jobame","\inputfilename","\outputfilename")}%
+% \to \everysetupsystem
% Some mechanisms (see x-res-01) use either \jobfilename or
% \jobfilename.somesuffix, in which case we need to use the
@@ -104,6 +114,10 @@
%D \NC \type{\operatingsystem} \NC \operatingsystem \NC \NR
%D \stoptabulate
+\appendtoks
+ \edef\outputresolution{\directsystemparameter\c!resolution}%
+\to \everysetupsystem
+
%D The system modes set by the setup command can be used in
%D situations like:
%D
@@ -138,9 +152,9 @@
[\c!directory=,
\c!n=0, % 0:unknown 1: one run 2: first 3: successive 4: final run
\c!resolution=600,% in dpi, no unit in mkiv
- %c!random=, % obsolete here
- \c!file=\jobname,
- \c!inputfile=\outputfilename,
+ % \c!random=, % obsolete here
+ % \c!file=\jobname,
+ % \c!inputfile=\outputfilename,
\c!type=unix, % windows is normally less sensitive to handle
\c!bodyfont=\normalizedlocalbodyfontsize] % of iets anders
@@ -150,14 +164,34 @@
%D But anyway, in \MKIV\ we avoid most of the complications anyway as we
%D deal with much at the \LUA\ end.
-\def\complexstart[#1]{\bgroup\getvalue{\e!start#1}}
-\def\complexstop [#1]{\getvalue{\e!stop #1}\egroup}
-
-\let\simplestart\bgroup
-\let\simplestop \egroup
-
-\definecomplexorsimple\start
-\definecomplexorsimple\stop
+\unexpanded\def\start
+ {\dosingleempty\syst_start}
+
+\def\syst_start
+ {\bgroup
+ \iffirstargument
+ \expandafter\syst_start_yes
+ \else
+ \expandafter\syst_start_nop
+ \fi}
+
+\def\syst_start_yes[#1]%
+ {\edef\m_syst_start_stop{#1}%
+ \ifx\m_syst_start_stop\empty
+ \let\syst_stop_indeed\donothing
+ \else\ifcsname\e!start\m_syst_start_stop\endcsname
+ \let\expandafter\syst_stop_indeed\csname\e!stop\m_syst_start_stop\endcsname
+ \csname\e!start\currentstartstop\expandafter\expandafter\expandafter\endcsname
+ \else
+ \let\syst_stop_indeed\donothing
+ \fi\fi}
+
+\def\syst_start_nop[#1]%
+ {\let\syst_stop_indeed\donothing}
+
+\unexpanded\def\stop
+ {\syst_stop_indeed
+ \egroup}
% \c!before \c!after \c!inbetween \c!commands \c!style \c!color
diff --git a/tex/context/base/core-two.lua b/tex/context/base/core-two.lua
index f94b102bc..d6e006e04 100644
--- a/tex/context/base/core-two.lua
+++ b/tex/context/base/core-two.lua
@@ -153,5 +153,5 @@ commands.savetwopassdata = jobpasses.save
commands.savetaggedtwopassdata = jobpasses.savetagged
function commands.doifelseintwopassdata(id,str)
- commands.testcase(inlist(id,str))
+ commands.doifelse(inlist(id,str))
end
diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua
index 1657a75e2..141f20cd3 100644
--- a/tex/context/base/core-uti.lua
+++ b/tex/context/base/core-uti.lua
@@ -20,6 +20,7 @@ saves much runtime but at the cost of more memory usage.</p>
local format, match = string.format, string.match
local next, type, tostring = next, type, tostring
local concat = table.concat
+local texcount = tex.count
local definetable = utilities.tables.definetable
local accesstable = utilities.tables.accesstable
@@ -29,7 +30,7 @@ local packers = utilities.packers
local allocate = utilities.storage.allocate
local mark = utilities.storage.mark
-local report_jobcontrol = logs.reporter("jobcontrol")
+local report_passes = logs.reporter("job","passes")
job = job or { }
local job = job
@@ -146,9 +147,7 @@ function job.save(filename) -- we could return a table but it can get pretty lar
for c=1,#comment do
f:write("-- ",comment[c],"\n")
end
- f:write("\n")
- f:write("local utilitydata = { }\n")
- f:write("\n")
+ f:write("\nlocal utilitydata = { }\n\n")
for l=1,#savelist do
local list = savelist[l]
local target = format("utilitydata.%s",list[1])
@@ -160,16 +159,13 @@ function job.save(filename) -- we could return a table but it can get pretty lar
if job.pack then
packers.pack(data,jobpacker,true)
end
- f:write(definetable(target),"\n")
- f:write(serialize(data,target,true,true),"\n")
+ f:write(definetable(target),"\n",serialize(data,target,true,true),"\n")
end
if job.pack then
packers.strip(jobpacker)
f:write(serialize(jobpacker,"utilitydata.job.packed",true,true),"\n")
end
- f:write("\n")
- f:write("return utilitydata\n")
- f:write("\n")
+ f:write("\nreturn utilitydata\n\n")
f:close()
end
statistics.stoptiming(_save_)
@@ -180,7 +176,7 @@ local function load(filename)
if data and data ~= "" then
local version = tonumber(match(data,"^-- version: ([%d%.]+)"))
if version ~= job.version then
- report_jobcontrol("version mismatch with jobfile: %s <> %s", version or "?", job.version)
+ report_passes("version mismatch: %s <> %s", version or "?", job.version)
else
local data = loadstring(data)
return data and data()
@@ -252,7 +248,7 @@ end)
statistics.register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
- local pages = tex.count['realpageno'] - 1
+ local pages = texcount['realpageno'] - 1
if pages > 1 then
return format("direct: %s, indirect: %s, total: %s (%i per page)", total-indirect, indirect, total, total/pages)
else
@@ -268,8 +264,8 @@ end)
function statistics.formatruntime(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
+ local shipped = texcount['nofshipouts']
+ local pages = texcount['realpageno'] - 1
if shipped > 0 or pages > 0 then
local persecond = shipped / runtime
if pages == 0 then pages = shipped end
diff --git a/tex/context/base/core-var.mkiv b/tex/context/base/core-var.mkiv
deleted file mode 100644
index 26559f246..000000000
--- a/tex/context/base/core-var.mkiv
+++ /dev/null
@@ -1,239 +0,0 @@
-%D \module
-%D [ file=core-var,
-%D version=1998.02.21,
-%D title=\CONTEXT\ Core 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 Core Macros / Variables}
-
-\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
-%D it here.
-
-%D \macros
-%D {every...}
-%D
-%D A few every's. Some are only used in \MKII\ or \MKIV.
-
-%D Output routine:
-
-\newtoks \everybeforeoutput
-\newtoks \everyafteroutput
-
-%D Shipout:
-
-\newtoks \everyshipout
-\newtoks \everybeforeshipout
-\newtoks \everyaftershipout
-\newtoks \everyfirstshipout
-\newtoks \everylastshipout
-
-%D End of run:
-
-\newtoks \everybye
-\newtoks \everygoodbye
-\newtoks \everynotabene
-
-%D Document
-
-\newtoks \everysetupdocument
-\newtoks \everyendoftextbody
-
-\newtoks \everystarttext
-\newtoks \everystoptext
-
-%D Purity:
-
-\newtoks \everyforgetall
-\newtoks \everycleanupfeatures
-
-\def\cleanupfeatures{\the\everycleanupfeatures}
-\def\forgetall {\the\everyforgetall}
-
-%D Page building:
-
-\newtoks \everybeforepagebody
-\newtoks \everyafterpagebody
-
-\let \everypagebody \everybeforepagebody % backward compatible, will become obsolete
-
-%D Floats:
-
-\newtoks \everyinsidefloat
-
-%D Sectioning:
-
-\newtoks \everyheadstart
-
-%D Par building (experimental, used in xml <p> .. </p>)
-
-\newtoks \everybeginofpar
-\newtoks \everyendofpar
-%newtoks \everyparflush
-
-\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:
-
-\newtoks \everylistentry
-\newtoks \everysavesortkeys
-
-%D Marks:
-
-\newtoks \everymarking
-
-%D Fonts:
-
-\newtoks \everyfont
-\newtoks \everyglobalbodyfont
-\newtoks \everydefinedfont
-
-\newevery \everybodyfont \EveryBodyFont
-\newevery \everyfontswitch \EveryFontSwitch
-
-\newtoks \everysetupbodyfont
-\newtoks \everyswitchtobodyfont
-
-%D Math:
-
-\newtoks \everybeforedisplayformula
-\newtoks \everymathematics
-
-\prependtoks \the\everymathematics \to \everymath
-\prependtoks \the\everymathematics \to \everydisplay
-
-%D Tables
-
-\newtoks \everytable
-
-%D State mess:
-
-\newtoks \everypushsomestate
-\newtoks \everypopsomestate
-
-\def\pushsomestates{\the\everypushsomestate}
-\def\popsomestates {\the\everypopsomestate }
-
-%D More generic (used to be pushcolor etc)
-
-\newtoks\everystarttextproperties
-\newtoks\everystoptextproperties
-
-\unexpanded\def\starttextproperties{\the\everystarttextproperties}
-\unexpanded\def\stoptextproperties {\the\everystoptextproperties}
-
-%D \macros
-%D {trialtypesetting}
-%D
-%D We disable trial typesetting in the output routine,
-%D just to be sure.
-
-\prependtoks \resettrialtypesetting \to \everybeforepagebody
-
-%D \macros
-%D {ifinpagebody,ifinsidecolumns,ifdoublesided,ifsinglesided}
-
-\newif \ifinpagebody
-\newif \ifinsidecolumns
-\newif \ifdoublesided \doublesidedfalse
-\newif \ifsinglesided \singlesidedtrue
-\newif \ifinsidefloat
-\newif \ifdoingblocks
-\newif \ifgridsnapping
-
-%D \macros
-%D {ifprocessingXML}
-%D
-%D We need this one even if no \XML\ is supported.
-
-% \newif\ifprocessingXML % old way
-
-%D \macros
-%D {ifproductionrun}
-%D
-%D This boolean can be used to bypass certain
-%D initializations.
-
-\newif\ifproductionrun \appendtoks \productionruntrue \to \everydump
-
-%D \macros
-%D {everyboxedcontent, ifboxedcontent,
-%D startboxedcontent, stopboxedcontent}
-%D
-%D This one is relatively new and will be used as a more
-%D robust test for inner situations.
-
-\newif \ifboxedcontent
-\newtoks\everyboxedcontent
-
-\appendtoks \boxedcontenttrue \to \everyboxedcontent
-
-\unexpanded\def\startboxedcontent{\bgroup\the\everyboxedcontent}
-\let\stopboxedcontent \egroup
-
-%D \macros
-%D {fastmode,silentmode}
-%D
-%D These commands are obsolete.
-
-\let\fastmode \relax
-\let\silentmode\relax
-
-%D \macros
-%D {defineselector,setupselector}
-%D
-%D \starttyping
-%D \defineselector[caption][max=2,n=2]
-%D
-%D \start
-%D \setupselector[caption][n=1]
-%D \placelist[figure][criterium=all]
-%D \stop
-%D
-%D \starttext
-%D \placefigure
-%D {\select{caption}{zapf}{\input zapf \relax}}
-%D {}
-%D \stoptext
-%D \stoptyping
-
-\unexpanded\def\defineselector{\dodoubleargument\dodefineselector}
-\unexpanded\def\setupselector {\dodoubleargument\dosetupselector}
-
-\def\dodefineselector[#1][#2]{\getparameters[\??sx#1][\c!max=2,\c!n=1,#2]}
-\def\dosetupselector [#1][#2]{\getparameters[\??sx#1][#2]}
-
-\unexpanded\def\select#1%
- {\filterfromnext
- {\executeifdefined{\??sx#1\c!max}1}
- {\executeifdefined{\??sx#1\c!n }1}}
-
-%D We store some original meanings, maybe in \type
-%D {math-ini}.
-
-\let\normalat \at
-\let\normalin \in
-\let\normalfrom \from
-%let\normalover \over
-\let\normalabout\about
-
-%D Add-ons:
-
-\let\setlayoutcomponentattribute \gobbleoneargument
-\let\resetlayoutcomponentattribute\relax
-\let\layoutcomponentboxattribute \empty
-
-\protect \endinput
diff --git a/tex/context/base/data-env.lua b/tex/context/base/data-env.lua
index 2d9787b91..f016881b5 100644
--- a/tex/context/base/data-env.lua
+++ b/tex/context/base/data-env.lua
@@ -12,7 +12,7 @@ local resolvers = resolvers
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
-local fileextname = file.extname
+local suffixonly = file.suffixonly
local formats = allocate()
local suffixes = allocate()
@@ -268,7 +268,7 @@ function resolvers.formatofvariable(str)
end
function resolvers.formatofsuffix(str) -- of file
- return suffixmap[fileextname(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
+ return suffixmap[suffixonly(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
end
function resolvers.variableofformat(str)
@@ -280,7 +280,7 @@ function resolvers.variableofformatorsuffix(str)
if v then
return v
end
- v = suffixmap[fileextname(str)]
+ v = suffixmap[suffixonly(str)]
if v then
return formats[v]
end
diff --git a/tex/context/base/data-exp.lua b/tex/context/base/data-exp.lua
index 66bbb56cb..550b61689 100644
--- a/tex/context/base/data-exp.lua
+++ b/tex/context/base/data-exp.lua
@@ -114,12 +114,14 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
for s in gmatch(str,"[^,]+") do
s = validate(s)
if s then
- n = n + 1 ; t[n] = s
+ n = n + 1
+ t[n] = s
end
end
else
for s in gmatch(str,"[^,]+") do
- n = n + 1 ; t[n] = s
+ n = n + 1
+ t[n] = s
end
end
if trace_expansions then
@@ -133,7 +135,7 @@ end
-- We could make the previous one public.
local function validate(s)
- s = collapsepath(s) -- already keeps the //
+ s = collapsepath(s) -- already keeps the trailing / and //
return s ~= "" and not find(s,"^!*unset/*$") and s
end
diff --git a/tex/context/base/data-ini.lua b/tex/context/base/data-ini.lua
index 2c263aada..773490785 100644
--- a/tex/context/base/data-ini.lua
+++ b/tex/context/base/data-ini.lua
@@ -10,7 +10,7 @@ local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string
local concat = table.concat
local next, type = next, type
-local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
+local filedirname, filebasename, filejoin = file.dirname, file.basename, file.join
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
diff --git a/tex/context/base/data-lua.lua b/tex/context/base/data-lua.lua
index 906a611ee..fec5856ea 100644
--- a/tex/context/base/data-lua.lua
+++ b/tex/context/base/data-lua.lua
@@ -6,167 +6,196 @@ if not modules then modules = { } end modules ['data-lua'] = {
license = "see context related readme files"
}
--- some loading stuff ... we might move this one to slot 2 depending
--- on the developments (the loaders must not trigger kpse); we could
--- of course use a more extensive lib path spec
+-- We overload the regular loader. We do so because we operate mostly in
+-- tds and use our own loader code. Alternatively we could use a more
+-- extensive definition of package.path and package.cpath but even then
+-- we're not done. Also, we now have better tracing.
+--
+-- -- local mylib = require("libtest")
+-- -- local mysql = require("luasql.mysql")
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+local concat = table.concat
+
+local trace_libraries = false
+
+trackers.register("resolvers.libraries", function(v) trace_libraries = v end)
+trackers.register("resolvers.locating", function(v) trace_libraries = v end)
local report_libraries = logs.reporter("resolvers","libraries")
local gsub, insert = string.gsub, table.insert
+local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
local unpack = unpack or table.unpack
+local is_readable = file.is_readable
local resolvers, package = resolvers, package
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
-local clibformats = { 'lib' }
+local libsuffixes = { 'tex', 'lua' }
+local clibsuffixes = { 'lib' }
+local libformats = { 'TEXINPUTS', 'LUAINPUTS' }
+local clibformats = { 'CLUAINPUTS' }
+
+local libpaths = nil
+local clibpaths = nil
+local libhash = { }
+local clibhash = { }
+local libextras = { }
+local clibextras = { }
-local _path_, libpaths, _cpath_, clibpaths
+local pattern = Cs(P("!")^0 / "" * (P("/") * P(-1) / "/" + P("/")^1 / "/" + 1)^0)
-function package.libpaths()
- if not _path_ or package.path ~= _path_ then
- _path_ = package.path
- libpaths = file.splitpath(_path_,";")
+local function cleanpath(path) --hm, don't we have a helper for this?
+ return resolvers.resolve(lpegmatch(pattern,path))
+end
+
+local function getlibpaths()
+ if not libpaths then
+ libpaths = { }
+ for i=1,#libformats do
+ local paths = resolvers.expandedpathlistfromvariable(libformats[i])
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not libhash[path] then
+ libpaths[#libpaths+1] = path
+ libhash[path] = true
+ end
+ end
+ end
end
return libpaths
end
-function package.clibpaths()
- if not _cpath_ or package.cpath ~= _cpath_ then
- _cpath_ = package.cpath
- clibpaths = file.splitpath(_cpath_,";")
+local function getclibpaths()
+ if not clibpaths then
+ clibpaths = { }
+ for i=1,#clibformats do
+ local paths = resolvers.expandedpathlistfromvariable(clibformats[i])
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not clibhash[path] then
+ clibpaths[#clibpaths+1] = path
+ clibhash[path] = true
+ end
+ end
+ end
end
return clibpaths
end
-local function thepath(...)
- local t = { ... } t[#t+1] = "?.lua"
- local path = file.join(unpack(t))
- if trace_locating then
- report_libraries("! appending '%s' to 'package.path'",path)
+package.libpaths = getlibpaths
+package.clibpaths = getclibpaths
+
+function package.extralibpath(...)
+ local paths = { ... }
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not libhash[path] then
+ if trace_libraries then
+ report_libraries("! extra lua path '%s'",path)
+ end
+ libextras[#libextras+1] = path
+ libpaths[#libpaths +1] = path
+ end
end
- return path
end
-local p_libpaths, a_libpaths = { }, { }
-
-function package.appendtolibpath(...)
- insert(a_libpath,thepath(...))
+function package.extraclibpath(...)
+ local paths = { ... }
+ for i=1,#paths do
+ local path = cleanpath(paths[i])
+ if not clibhash[path] then
+ if trace_libraries then
+ report_libraries("! extra lib path '%s'",path)
+ end
+ clibextras[#clibextras+1] = path
+ clibpaths[#clibpaths +1] = path
+ end
+ end
end
-function package.prependtolibpath(...)
- insert(p_libpaths,1,thepath(...))
+if not package.loaders[-2] then
+ -- use package-path and package-cpath
+ package.loaders[-2] = package.loaders[2]
end
--- beware, we need to return a loadfile result !
+local function loadedaslib(resolved,rawname)
+ return package.loadlib(resolved,"luaopen_" .. gsub(rawname,"%.","_"))
+end
-local function loaded(libpaths,name,simple)
- for i=1,#libpaths do -- package.path, might become option
- local libpath = libpaths[i]
- local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
+local function loadedbylua(name)
+ if trace_libraries then
+ report_libraries("! locating %q using normal loader",name)
end
+ local resolved = package.loaders[-2](name)
end
-package.loaders[2] = function(name) -- was [#package.loaders+1]
- 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
+local function loadedbyformat(name,rawname,suffixes,islib)
+ if trace_libraries then
+ report_libraries("! locating %q as %q using formats %q",rawname,name,concat(suffixes))
end
- for i=1,#libformats do
- local format = libformats[i]
+ for i=1,#suffixes do -- so we use findfile and not a lookup loop
+ local format = suffixes[i]
local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
+ if trace_libraries then
+ report_libraries("! checking for %q' using format %q",name,format)
end
if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
+ if trace_libraries then
+ report_libraries("! lib %q located on %q",name,resolved)
end
- return loadfile(resolved)
- end
- end
- -- libpaths
- local libpaths, clibpaths = package.libpaths(), package.clibpaths()
- local simple = gsub(name,"%.lua$","")
- local simple = gsub(simple,"%.","/")
- local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple)
- if resolved then
- return resolved
- end
- --
- local libname = file.addsuffix(simple,os.libsuffix)
- for i=1,#clibformats do
- -- better have a dedicated loop
- local format = clibformats[i]
- local paths = resolvers.expandedpathlistfromvariable(format)
- for p=1,#paths do
- local path = paths[p]
- local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
- end
- return package.loadlib(resolved,name)
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
end
end
end
- for i=1,#clibpaths do -- package.path, might become option
- local libpath = clibpaths[i]
- local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
+end
+
+local function loadedbypath(name,rawname,paths,islib,what)
+ if trace_libraries then
+ report_libraries("! locating %q as %q on %q paths",rawname,name,what)
+ end
+ for p=1,#paths do
+ local path = paths[p]
+ local resolved = file.join(path,name)
+ if trace_libraries then -- mode detail
+ report_libraries("! checking for %q using %q path %q",name,what,path)
end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
+ if is_readable(resolved) then
+ if trace_libraries then
+ report_libraries("! lib %q located on %q",name,resolved)
+ end
+ if islib then
+ return loadedaslib(resolved,rawname)
+ else
+ return loadfile(resolved)
end
- return package.loadlib(resolved,name)
- end
- end
- -- just in case the distribution is messed up
- if trace_loading then -- more detail
- report_libraries("! checking for '%s' using 'luatexlibs': '%s'",name)
- end
- local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
- if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
end
- return loadfile(resolved)
end
- if trace_locating then
- report_libraries('? unable to locate lib: %s',name)
- end
--- return "unable to locate " .. name
end
-resolvers.loadlualib = require
-
--- -- -- --
+local function notloaded(name)
+ if trace_libraries then
+ report_libraries("? unable to locate library %q",name)
+ end
+end
-package.obsolete = package.obsolete or { }
+package.loaders[2] = function(name)
+ local thename = gsub(name,"%.","/")
+ local luaname = file.addsuffix(thename,"lua")
+ local libname = file.addsuffix(thename,os.libsuffix)
+ return
+ loadedbyformat(luaname,name,libsuffixes, false)
+ or loadedbyformat(libname,name,clibsuffixes, true)
+ or loadedbypath (luaname,name,getlibpaths (),false,"lua")
+ or loadedbypath (luaname,name,getclibpaths(),false,"lua")
+ or loadedbypath (libname,name,getclibpaths(),true, "lib")
+ or loadedbylua (name)
+ or notloaded (name)
+end
-package.append_libpath = appendtolibpath -- will become obsolete
-package.prepend_libpath = prependtolibpath -- will become obsolete
+-- package.loaders[3] = nil
+-- package.loaders[4] = nil
-package.obsolete.append_libpath = appendtolibpath -- will become obsolete
-package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+resolvers.loadlualib = require
diff --git a/tex/context/base/data-pre.lua b/tex/context/base/data-pre.lua
index 5b25c5f87..40b430bf2 100644
--- a/tex/context/base/data-pre.lua
+++ b/tex/context/base/data-pre.lua
@@ -23,6 +23,8 @@ local gsub = string.gsub
local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+local joinpath, basename, dirname = file.join, file.basename, file.dirname
+local getmetatable, rawset, type = getmetatable, rawset, type
-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
@@ -64,28 +66,43 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
+ return cleanpath(basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.dirname((fullname ~= "" and fullname) or str))
+ return cleanpath(dirname((fullname ~= "" and fullname) or str))
end
prefixes.selfautoloc = function(str)
- return cleanpath(file.join(getenv('SELFAUTOLOC'),str))
+ return cleanpath(joinpath(getenv('SELFAUTOLOC'),str))
end
prefixes.selfautoparent = function(str)
- return cleanpath(file.join(getenv('SELFAUTOPARENT'),str))
+ return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str))
end
prefixes.selfautodir = function(str)
- return cleanpath(file.join(getenv('SELFAUTODIR'),str))
+ return cleanpath(joinpath(getenv('SELFAUTODIR'),str))
end
prefixes.home = function(str)
- return cleanpath(file.join(getenv('HOME'),str))
+ return cleanpath(joinpath(getenv('HOME'),str))
+end
+
+local function toppath()
+ local pathname = dirname(inputstack[#inputstack] or "")
+ if pathname == "" then
+ return "."
+ else
+ return pathname
+ end
+end
+
+resolvers.toppath = toppath
+
+prefixes.toppath = function(str)
+ return cleanpath(joinpath(toppath(),str))
end
prefixes.env = prefixes.environment
@@ -121,6 +138,8 @@ function resolvers.resetresolve(str)
resolved, abstract = { }, { }
end
+-- todo: use an lpeg (see data-lua for !! / stripper)
+
local function resolve(str) -- use schemes, this one is then for the commandline only
if type(str) == "table" then
local t = { }
@@ -146,7 +165,7 @@ end
resolvers.resolve = resolve
resolvers.unresolve = unresolve
-if os.uname then
+if type(os.uname) == "function" then
for k, v in next, os.uname() do
if not prefixes[k] then
@@ -158,11 +177,17 @@ end
if os.type == "unix" then
+ -- We need to distringuish between a prefix and something else : so we
+ -- have a special repath variant for linux. Also, when a new prefix is
+ -- defined, we need to remake the matcher.
+
local pattern
local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
local colon = P(":")
- local p
for k, v in table.sortedpairs(prefixes) do
if p then
p = P(k) + p
@@ -171,9 +196,6 @@ if os.type == "unix" then
end
end
pattern = Cs((p * colon + colon/";" + P(1))^0)
- if t then
- t[k] = v
- end
end
makepattern()
diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua
index 7206c0d78..9236cbe02 100644
--- a/tex/context/base/data-res.lua
+++ b/tex/context/base/data-res.lua
@@ -24,11 +24,12 @@ local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local filedirname = file.dirname
local filebasename = file.basename
-local fileextname = file.extname
+local suffixonly = file.suffixonly
local filejoin = file.join
local collapsepath = file.collapsepath
local joinpath = file.joinpath
local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -52,7 +53,7 @@ resolvers.cacheversion = '1.0.1'
resolvers.configbanner = ''
resolvers.homedir = environment.homedir
resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" }
-resolvers.luacnfname = 'texmfcnf.lua'
+resolvers.luacnfname = "texmfcnf.lua"
resolvers.luacnfstate = "unknown"
-- The web2c tex binaries as well as kpse have built in paths for the configuration
@@ -332,7 +333,7 @@ end
local function identify_configuration_files()
local specification = instance.specification
if #specification == 0 then
- local cnfspec = getenv('TEXMFCNF')
+ local cnfspec = getenv("TEXMFCNF")
if cnfspec == "" then
cnfspec = resolvers.luacnfspec
resolvers.luacnfstate = "default"
@@ -420,7 +421,7 @@ local function load_configuration_files()
-- we push the value into the main environment (osenv) so
-- that it takes precedence over the default one and therefore
-- also over following definitions
- resolvers.setenv('TEXMFCNF',cnfspec) -- resolves prefixes
+ resolvers.setenv("TEXMFCNF",cnfspec) -- resolves prefixes
-- we now identify and load the specified configuration files
instance.specification = { }
identify_configuration_files()
@@ -468,10 +469,11 @@ end
local function locate_file_databases()
-- todo: cache:// and tree:// (runtime)
- local texmfpaths = resolvers.expandedpathlist('TEXMF')
+ local texmfpaths = resolvers.expandedpathlist("TEXMF")
if #texmfpaths > 0 then
for i=1,#texmfpaths do
local path = collapsepath(texmfpaths[i])
+ path = gsub(path,"/+$","") -- in case $HOME expands to something with a trailing /
local stripped = lpegmatch(inhibitstripper,path) -- the !! thing
if stripped ~= "" then
local runtime = stripped == path
@@ -600,9 +602,9 @@ function resolvers.prependhash(type,name,cache)
end
function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash
- local t = resolvers.splitpath(getenv('TEXMF'))
+ local t = resolvers.splitpath(getenv("TEXMF")) -- okay?
insert(t,1,specification)
- local newspec = concat(t,";")
+ local newspec = concat(t,",") -- not ;
if instance.environment["TEXMF"] then
instance.environment["TEXMF"] = newspec
elseif instance.variables["TEXMF"] then
@@ -677,14 +679,19 @@ function resolvers.resetextrapath()
end
function resolvers.registerextrapath(paths,subpaths)
+ paths = settings_to_array(paths)
+ subpaths = settings_to_array(subpaths)
local ep = instance.extra_paths or { }
local oldn = #ep
local newn = oldn
- if paths and paths ~= "" then
- if subpaths and subpaths ~= "" then
- for p in gmatch(paths,"[^,]+") do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
+ local nofpaths = #paths
+ local nofsubpaths = #subpaths
+ if nofpaths > 0 then
+ if nofsubpaths > 0 then
+ for i=1,nofpaths do
+ local p = paths[i]
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
local ps = p .. "/" .. s
if not done[ps] then
newn = newn + 1
@@ -694,7 +701,8 @@ function resolvers.registerextrapath(paths,subpaths)
end
end
else
- for p in gmatch(paths,"[^,]+") do
+ for i=1,nofpaths do
+ local p = paths[i]
if not done[p] then
newn = newn + 1
ep[newn] = resolvers.cleanpath(p)
@@ -702,10 +710,10 @@ function resolvers.registerextrapath(paths,subpaths)
end
end
end
- elseif subpaths and subpaths ~= "" then
+ elseif nofsubpaths > 0 then
for i=1,oldn do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
+ for j=1,nofsubpaths do
+ local s = subpaths[j]
local ps = ep[i] .. "/" .. s
if not done[ps] then
newn = newn + 1
@@ -783,18 +791,21 @@ function resolvers.expandedpathlist(str)
return { }
elseif instance.savelists then
str = lpegmatch(dollarstripper,str)
- if not instance.lists[str] then -- cached
- local lst = made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
- instance.lists[str] = expandedpathfromlist(lst)
- end
- return instance.lists[str]
+ local lists = instance.lists
+ local lst = lists[str]
+ if not lst then
+ local l = made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ lst = expandedpathfromlist(l)
+ lists[str] = lst
+ end
+ return lst
else
local lst = resolvers.splitpath(resolvers.expansion(str))
return made_list(instance,expandedpathfromlist(lst))
end
end
-function resolvers.expandedpathlistfromvariable(str) -- brrr
+function resolvers.expandedpathlistfromvariable(str) -- brrr / could also have cleaner ^!! /$ //
str = lpegmatch(dollarstripper,str)
local tmp = resolvers.variableofformatorsuffix(str)
return resolvers.expandedpathlist(tmp ~= "" and tmp or str)
@@ -951,7 +962,7 @@ local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
local collect_instance_files
local function find_analyze(filename,askedformat,allresults)
- local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ local filetype, wantedfiles, ext = '', { }, suffixonly(filename)
-- too tricky as filename can be bla.1.2.3:
--
-- if not suffixmap[ext] then
@@ -1029,7 +1040,7 @@ local function find_qualified(filename,allresults) -- this one will be split too
if trace_detail then
report_resolving("locating qualified file '%s'", filename)
end
- local forcedname, suffix = "", fileextname(filename)
+ local forcedname, suffix = "", suffixonly(filename)
if suffix == "" then -- why
local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
if format_suffixes then
diff --git a/tex/context/base/data-sch.lua b/tex/context/base/data-sch.lua
index 253adb9f6..569fa5c94 100644
--- a/tex/context/base/data-sch.lua
+++ b/tex/context/base/data-sch.lua
@@ -6,26 +6,26 @@ if not modules then modules = { } end modules ['data-sch'] = {
license = "see context related readme files"
}
-local http = require("socket.http")
-local ltn12 = require("ltn12")
+local loadstring = loadstring
local gsub, concat, format = string.gsub, table.concat, string.format
local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
-local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end)
-
+local trace_schemes = false trackers.register("resolvers.schemes",function(v) trace_schemes = v end)
local report_schemes = logs.reporter("resolvers","schemes")
-local resolvers = resolvers
+local http = require("socket.http")
+local ltn12 = require("ltn12")
-resolvers.schemes = resolvers.schemes or { }
-local schemes = resolvers.schemes
-schemes.threshold = 24 * 60 * 60
+local resolvers = resolvers
+local schemes = resolvers.schemes or { }
+resolvers.schemes = schemes
-directives.register("schemes.threshold", function(v) schemes.threshold = tonumber(v) or schemes.threshold end)
+local cleaners = { }
+schemes.cleaners = cleaners
-local cleaners = { }
+local threshold = 24 * 60 * 60
-schemes.cleaners = cleaners
+directives.register("schemes.threshold", function(v) threshold = tonumber(v) or threshold end)
function cleaners.none(specification)
return specification.original
@@ -53,7 +53,7 @@ end
local cached, loaded, reused, thresholds, handlers = { }, { }, { }, { }, { }
-local function runcurl(name,cachename) -- will use sockets instead or the curl library
+local function runcurl(name,cachename) -- we use sockets instead or the curl library when possible
local command = "curl --silent --create-dirs --output " .. cachename .. " " .. name
os.spawn(command)
end
@@ -65,8 +65,7 @@ local function fetch(specification)
local cachename = caches.setfirstwritablefile(cleanname,"schemes")
if not cached[original] then
statistics.starttiming(schemes)
- if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) >
- (thresholds[protocol] or schemes.threshold)) then
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification) > (thresholds[protocol] or threshold)) then
cached[original] = cachename
local handler = handlers[scheme]
if handler then
@@ -112,14 +111,14 @@ end
local opener = openers.file
local loader = loaders.file
-local function install(scheme,handler,threshold)
+local function install(scheme,handler,newthreshold)
handlers [scheme] = handler
loaded [scheme] = 0
reused [scheme] = 0
finders [scheme] = finder
openers [scheme] = opener
loaders [scheme] = loader
- thresholds[scheme] = threshold or schemes.threshold
+ thresholds[scheme] = newthreshold or threshold
end
schemes.install = install
@@ -160,11 +159,42 @@ statistics.register("scheme handling time", function()
end
local n = nl + nr
if n > 0 then
- l = (nl > 0 and concat(l)) or "none"
- r = (nr > 0 and concat(r)) or "none"
+ l = nl > 0 and concat(l) or "none"
+ r = nr > 0 and concat(r) or "none"
return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
- statistics.elapsedtime(schemes), n, schemes.threshold, l, r)
+ statistics.elapsedtime(schemes), n, threshold, l, r)
else
return nil
end
end)
+
+-- We provide a few more helpers:
+
+----- http = require("socket.http")
+local httprequest = http.request
+local toquery = url.toquery
+
+-- local function httprequest(url)
+-- return os.resultof(format("curl --silent %q", url))
+-- end
+
+local function fetchstring(url,data)
+ local q = data and toquery(data)
+ if q then
+ url = url .. "?" .. q
+ end
+ local reply = httprequest(url)
+ return reply -- just one argument
+end
+
+schemes.fetchstring = fetchstring
+
+function schemes.fetchtable(url,data)
+ local reply = fetchstring(url,data)
+ if reply then
+ local s = loadstring("return " .. reply)
+ if s then
+ return s()
+ end
+ end
+end
diff --git a/tex/context/base/data-tex.lua b/tex/context/base/data-tex.lua
index 6cb361699..2105f29f4 100644
--- a/tex/context/base/data-tex.lua
+++ b/tex/context/base/data-tex.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['data-tex'] = {
}
local char = string.char
+local insert, remove = table.insert, table.remove
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -51,6 +52,10 @@ appendgroup(textlineactions,"after" ) -- user
local ctrl_d = char( 4) -- unix
local ctrl_z = char(26) -- windows
+resolvers.inputstack = resolvers.inputstack or { }
+
+local inputstack = resolvers.inputstack
+
function helpers.textopener(tag,filename,filehandle,coding)
local lines
local t_filehandle = type(filehandle)
@@ -92,6 +97,7 @@ function helpers.textopener(tag,filename,filehandle,coding)
lines[noflines] = nil
end
logs.show_open(filename)
+ insert(inputstack,filename)
return {
filename = filename,
noflines = noflines,
@@ -101,6 +107,7 @@ function helpers.textopener(tag,filename,filehandle,coding)
report_tex("%s closer, '%s' closed",tag,filename)
end
logs.show_close(filename)
+ remove(inputstack)
t = nil
end,
reader = function(self)
diff --git a/tex/context/base/data-vir.lua b/tex/context/base/data-vir.lua
index 89359c19a..dff780fc7 100644
--- a/tex/context/base/data-vir.lua
+++ b/tex/context/base/data-vir.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['data-vir'] = {
license = "see context related readme files"
}
-local format = string.format
+local format, validstrings = string.format, string.valid
local trace_virtual = false
local report_virtual = logs.reporter("resolvers","virtual")
@@ -18,7 +18,9 @@ local resolvers = resolvers
local finders, openers, loaders, savers = resolvers.finders, resolvers.openers, resolvers.loaders, resolvers.savers
-local data, n, template = { }, 0, "virtual://%s.%s" -- hm, number can be query
+local data = { }
+local n = 0 -- hm, number can be query
+local template = "virtual://%s.%s"
function savers.virtual(specification,content)
n = n + 1 -- one number for all namespaces
@@ -54,7 +56,7 @@ function openers.virtual(specification)
if trace_virtual then
report_virtual("opener, file '%s' opened",original)
end
- data[original] = nil
+ data[original] = nil -- when we comment this we can have error messages
-- With utf-8 we signal that no regime is to be applied!
return openers.helpers.textopener("virtual",original,d,"utf-8")
else
diff --git a/tex/context/base/data-zip.lua b/tex/context/base/data-zip.lua
index 676a2df96..7e8ea3a39 100644
--- a/tex/context/base/data-zip.lua
+++ b/tex/context/base/data-zip.lua
@@ -14,11 +14,17 @@ local trace_locating = false trackers.register("resolvers.locating", function(v
local report_zip = logs.reporter("resolvers","zip")
--- zip:///oeps.zip?name=bla/bla.tex
--- zip:///oeps.zip?tree=tex/texmf-local
--- zip:///texmf.zip?tree=/tex/texmf
--- zip:///texmf.zip?tree=/tex/texmf-local
--- zip:///texmf-mine.zip?tree=/tex/texmf-projects
+--[[ldx--
+<p>We use a url syntax for accessing the zip file itself and file in it:</p>
+
+<typing>
+zip:///oeps.zip?name=bla/bla.tex
+zip:///oeps.zip?tree=tex/texmf-local
+zip:///texmf.zip?tree=/tex/texmf
+zip:///texmf.zip?tree=/tex/texmf-local
+zip:///texmf-mine.zip?tree=/tex/texmf-projects
+</typing>
+--ldx]]--
local resolvers = resolvers
diff --git a/tex/context/base/enco-ini.mkiv b/tex/context/base/enco-ini.mkiv
index a942d5110..3b0cbc9fc 100644
--- a/tex/context/base/enco-ini.mkiv
+++ b/tex/context/base/enco-ini.mkiv
@@ -43,22 +43,32 @@
%D \macros
%D {defineaccent, definecharacter, definecommand}
-\unexpanded\def\dodefineaccentcommand#1%
- {\setevalue{\string#1}{\noexpand\dohandleaccent{\string#1}}}
-
-\unexpanded\def\dodefineaccent#1#2#3% no spaces, used low level
- {\setvalue{\??ac\string#1\string#2\empty}{#3}}
+\installcorenamespace{accents}
\unexpanded\def\defineaccent#1 #2 #3 %
- {\dodefineaccentcommand{#1}%
- \dodefineaccent{#1}{#2}{#3}}
-
-\def\dohandleaccent#1#2%
- {\ifcsname\??ac\string#1#2\empty\endcsname
- \csname\??ac\string#1#2\empty\endcsname
- \else\ifcsname\??ac\string#1\string#2\empty\endcsname
- \csname\??ac\string#1\string#2\empty\endcsname
- \fi\fi}
+ {\enco_define_accent_command{#1}%
+ \enco_define_accent{#1}{#2}{#3}}
+
+\unexpanded\def\enco_define_accent_command#1%
+ {\setevalue{\string#1}{\noexpand\enco_handle_accent{\string#1}}}
+
+\unexpanded\def\enco_define_accent#1#2#3% no spaces, used low level
+ {\setvalue{\??accents\string#1\string#2\empty}{#3}}
+
+\def\enco_handle_accent#1#2% expandable because we want them in the tuc file
+ {\csname\??accents
+ \ifcsname\??accents\string#1#2\empty\endcsname
+ \string#1#2\empty
+ \else\ifcsname\??accents\string#1\string#2\empty\endcsname
+ \string#1\string#2\empty
+ \else
+ \empty
+ \fi\fi
+ \endcsname}
+
+\let\dohandleaccent \enco_handle_accent % maybe useful
+\let\dodefineaccent \enco_define_accent % used at the lua end
+\let\dodefineaccentcommand\enco_define_accent_command % used at the lua end
\unexpanded\def\definecharacter#1 #2 %
{\doifnumberelse{\string#2}
@@ -77,15 +87,15 @@
%D Accent handling (try to avoid this):
-\newbox\accenttestbox % no longer global so we could use \scratchbox
+\newbox\b_enco_accent
\def\buildmathaccent#1%
{\mathaccent#1 }
\unexpanded\def\buildtextaccent#1#2% we could do all at the lua end
{\begingroup % but that's no fun (yet)
- \setbox\accenttestbox\hbox{#1}%
- \scratchcounter\cldcontext{nodes.firstcharinbox(\number\accenttestbox)}\relax
+ \setbox\b_enco_accent\hbox{#1}%
+ \scratchcounter\cldcontext{nodes.firstcharinbox(\number\b_enco_accent)}\relax
\ifcase\scratchcounter\else\accent\scratchcounter\fi
\relax#2%
\endgroup}
@@ -105,7 +115,7 @@
\hidewidth
\hskip#2\wd0
\hskip-#3\slantperpoint % in plain 1ex * dimenless value
- \vbox to .2ex{\box0\vss}\hidewidth
+ \vbox to .2\exheight{\box0\vss}\hidewidth
\crcr}}}
\unexpanded\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}}
@@ -128,7 +138,8 @@
\egroup
\egroup}
-\def\buildtextgrave{\topaccent{0pt}{0}{15}{\textgrave}} % e.g.
+\unexpanded\def\buildtextgrave
+ {\topaccent{0pt}{0}{15}{\textgrave}} % e.g.
\unexpanded\def\definemathaccent#1 #2%
{\setvalue{#1}{\mathaccent#2 }}
@@ -224,7 +235,7 @@
% left-overs (some day in private unicode space, so that we can roundtrip)
-\unexpanded\def\textblacksquare {\dontleavehmode\hbox{\vrule\!!width.3\s!em\!!height.4\s!em\!!depth-.1\s!em}}
+\unexpanded\def\textblacksquare {\dontleavehmode\hbox{\vrule\s!width.3\s!em\s!height.4\s!em\s!depth-.1\s!em}}
\unexpanded\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}}
\unexpanded\def\schwagrave {\buildtextgrave\schwa}
@@ -244,28 +255,28 @@
\let\textvisiblespace\normalcontrolspace
\unexpanded\def\fastcontrolspace % no glyph resolving after first (use grouped)
- {\dofastcontrolspace}
+ {\enco_fast_control_space}
-\def\dofastcontrolspace
+\def\enco_fast_control_space
{\iffontchar\font\textcontrolspace
- \nofastfallbackcontrolspace
+ \enco_fast_control_space_nop
\else
- \dofastfallbackcontrolspace
+ \enco_fast_control_space_yes
\fi
- \dofastcontrolspace}
+ \enco_fast_control_space}
-\newbox\controlspacebox
+\newbox\b_enco_control_space
-\def\nofastfallbackcontrolspace
- {\let\dofastcontrolspace\textcontrolspace}
+\def\enco_fast_control_space_nop
+ {\let\enco_fast_control_space\textcontrolspace}
-\def\dofastfallbackcontrolspace
- {\setbox\controlspacebox\hbox{\space}%
- \setbox\controlspacebox\hbox to \wd\controlspacebox{\hss\fallbackcontrolspace\hss}%
- \let\dofastcontrolspace\flushcontrolspacebox}
+\def\enco_fast_control_space_yes
+ {\setbox\b_enco_control_space\hbox{\space}%
+ \setbox\b_enco_control_space\hbox to \wd\b_enco_control_space{\hss\fallbackcontrolspace\hss}%
+ \let\enco_fast_control_space\flushcontrolspacebox}
\def\flushcontrolspacebox
- {\copy\controlspacebox}
+ {\copy\b_enco_control_space}
% a few defaults (\<whatever>{}), we really need the verbose \empty as it will be
% stringified .. anyhow, we define this at the lua end now but keep it here as a
@@ -289,39 +300,39 @@
% from enco-mis:
-\def\fakepercent
- {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25em/\kern-.2em\normalsubscript{\scriptscriptstyle0}}}
+\unexpanded\def\fakepercent
+ {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle0}}}
-\def\fakeperthousand
- {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25em/\kern-.2em\normalsubscript{\scriptscriptstyle00}}}
+\unexpanded\def\fakeperthousand
+ {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle00}}}
-\def\fakepermine
+\unexpanded\def\fakepermine
{\dontleavehmode
\bgroup
\setbox\scratchbox\hbox
{\mathematics{+}}%
\hbox to \wd\scratchbox
{\hss
- \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4em/\kern-.3em\normalsubscript{\scriptscriptstyle-}}%
+ \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4\emwidth/\kern-.3\emwidth\normalsubscript{\scriptscriptstyle-}}%
\hss}%
\egroup}
%D A smaller and bolder variant, more like the math and monospaced ones.
-\def\fakeunderscore
+\unexpanded\def\fakeunderscore
{\relax\ifmmode
- \vrule\!!depth .12\fontexheight\mathstylefont\normalmathstyle\!!width \fontinterwordspace\mathstylefont\normalmathstyle\!!height\zeropoint\relax
+ \vrule\s!depth .12\fontexheight\mathstylefont\normalmathstyle\s!width \fontinterwordspace\mathstylefont\normalmathstyle\s!height\zeropoint\relax
\else
- \dontleavehmode\hbox{\vrule\!!depth .12\fontexheight\font\!!width \fontinterwordspace\font\!!height\zeropoint}%
+ \dontleavehmode\hbox{\vrule\s!depth .12\fontexheight\font\s!width \fontinterwordspace\font\s!height\zeropoint}%
\fi}
-\def\fakeunderscores{\let\_\fakeunderscore}
-\def\textunderscores{\let\_\textunderscore}
+\unexpanded\def\fakeunderscores{\let\_\fakeunderscore}
+\unexpanded\def\textunderscores{\let\_\textunderscore}
\textunderscores
-\ifx\mathunderscore\undefined \let\mathunderscore\fakeunderscore \fi
-\ifx\textunderscore\undefined \let\textunderscore\fakeunderscore \fi
+\ifdefined\mathunderscore \else \let\mathunderscore\fakeunderscore \fi
+\ifdefined\textunderscore \else \let\textunderscore\fakeunderscore \fi
\unexpanded\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi}
@@ -349,7 +360,7 @@
\def\periodsdefault{3} % was 5, but now it's like \unknown
\unexpanded\def\periods
- {\dosingleempty\doperiods}
+ {\dosingleempty\enco_periods}
% \def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2
% {\dontleavehmode
@@ -361,7 +372,7 @@
%
% better for export:
-\unexpanded\def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2
+\unexpanded\def\enco_periods[#1]% todo: also n=,width= or maybe just #1,#2
{\dontleavehmode
\hbox\bgroup
\setbox\scratchbox\hbox to \periodswidth{\hss.\hss}%
@@ -377,4 +388,8 @@
%
% Hello\fourdots\ World\fourdots \par Hello\fourdots\ World.
+\appendtoks
+ \let\buildtextaccent\secondoftwoarguments
+\to \everysimplifycommands
+
\protect \endinput
diff --git a/tex/context/base/file-ini.lua b/tex/context/base/file-ini.lua
index 4f8b5b6e3..1872ed3d3 100644
--- a/tex/context/base/file-ini.lua
+++ b/tex/context/base/file-ini.lua
@@ -7,9 +7,8 @@ if not modules then modules = { } end modules ['file-ini'] = {
}
--[[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>
+<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'/> end.</p>
--ldx]]--
resolvers.jobs = resolvers.jobs or { }
diff --git a/tex/context/base/file-ini.mkvi b/tex/context/base/file-ini.mkvi
index b0f6244aa..989241dd1 100644
--- a/tex/context/base/file-ini.mkvi
+++ b/tex/context/base/file-ini.mkvi
@@ -73,15 +73,17 @@
%D \popendofline
%D \stoptyping
+\installsystemnamespace{eolstack}
+
\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
+ \expandafter\chardef\csname\??eolstack\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
+ {\catcode\endoflineasciicode\csname\??eolstack\number\c_system_files_eol_level\endcsname
\advance\c_system_files_eol_level\minusone}
\unexpanded\def\restoreendofline
@@ -101,11 +103,11 @@
\the\everystartreadingfile
\pushcatcodetable % saveguard
\setcatcodetable\ctxcatcodes
- \ctxlua{regimes.push()}}% temporarily this way
+ \ctxcommand{pushregime()}}% temporarily this way
\unexpanded\def\stopreadingfile
{\popcatcodetable % saveguard
- \ctxlua{regimes.pop()}% temporarily this way
+ \ctxcommand{popregime()}% temporarily this way
\the\everystopreadingfile
\global\advance\readingfilelevel\minusone}
@@ -203,11 +205,13 @@
%D This command obeys the standard method for locating files. We could
%D move this function to the \LUA\ end.
+\installsystemnamespace {fileonce}
+
\unexpanded\def\doonlyonce#whatever%
- {\ifcsname\??fi:#whatever\endcsname
+ {\ifcsname\??fileonce#whatever\endcsname
\expandafter\gobbleoneargument
\else
- \letgvalue{\??fi:#whatever}\relax
+ \letgvalue{\??fileonce#whatever}\relax
\expandafter\firstofoneargument
\fi}
@@ -215,11 +219,11 @@
{\doonlyonce{#name}{\doiffileelse{#name}{\inputgivenfile{#name}}\donothing}}
\unexpanded\def\doendinputonce#name%
- {\ifcsname\??fi:#name\endcsname
+ {\ifcsname\??fileonce#name\endcsname
\expandafter\endinput
\fi}
\unexpanded\def\forgetdoingonce#whatever%
- {\global\letbeundefined{\??fi:#whatever}}
+ {\global\letbeundefined{\??fileonce#whatever}}
\protect \endinput
diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua
index 992e4b7ec..6be901a9f 100644
--- a/tex/context/base/file-job.lua
+++ b/tex/context/base/file-job.lua
@@ -9,8 +9,9 @@ if not modules then modules = { } end modules ['file-job'] = {
-- 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 format, gsub, match, find = string.format, string.gsub, string.match, string.find
local insert, remove, concat = table.insert, table.remove, table.concat
+local validstring = string.valid
local commands, resolvers, context = commands, resolvers, context
@@ -18,25 +19,41 @@ local trace_jobfiles = false trackers.register("system.jobfiles", function(v)
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
+local texsetcount = tex.setcount
+local elements = interfaces.elements
+local constants = interfaces.constants
+local variables = interfaces.variables
+local logsnewline = logs.newline
+local logspushtarget = logs.pushtarget
+local logspoptarget = logs.poptarget
+local settings_to_array = utilities.parsers.settings_to_array
+local write_nl = texio.write_nl
+local allocate = utilities.storage.allocate
+
+local nameonly = file.nameonly
+local suffixonly = file.suffix
+local basename = file.basename
+local addsuffix = file.addsuffix
+local removesuffix = file.removesuffix
+local dirname = file.dirname
+local joinpath = file.join
+local is_qualified_path = file.is_qualified_path
+
+local cleanpath = resolvers.cleanpath
+local inputstack = resolvers.inputstack
+
+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
+ if 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 ""
@@ -59,7 +76,7 @@ function commands.doifinputfileelse(name)
end
function commands.locatefilepath(name)
- context(file.dirname(findctxfile(name)))
+ context(dirname(findctxfile(name)))
end
function commands.usepath(paths)
@@ -74,6 +91,10 @@ function commands.allinputpaths()
context(concat(resolvers.instance.extra_paths or { },","))
end
+function commands.setdocumentfilenames()
+ environment.initializefilenames()
+end
+
function commands.usezipfile(name,tree)
if tree and tree ~= "" then
resolvers.usezipfile(format("zip:///%s?tree=%s",name,tree))
@@ -156,7 +177,7 @@ end
--
local action = function(name,foundname) input(foundname) end
-local failure = function(name,foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown tex file %q",name) end
local function usetexfile(name,onlyonce,notext)
startprocessing(name,notext)
@@ -171,7 +192,7 @@ local function usetexfile(name,onlyonce,notext)
end
local action = function(name,foundname) dofile(foundname) end
-local failure = function(name,foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown lua file %q",name) end
local function useluafile(name,onlyonce,notext)
uselibrary {
@@ -184,7 +205,7 @@ local function useluafile(name,onlyonce,notext)
end
local action = function(name,foundname) dofile(foundname) end
-local failure = function(name,foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown cld file %q",name) end
local function usecldfile(name,onlyonce,notext)
startprocessing(name,notext)
@@ -199,7 +220,7 @@ local function usecldfile(name,onlyonce,notext)
end
local action = function(name,foundname) context.xmlprocess(foundname,"main","") end
-local failure = function(name,foundname) end
+local failure = function(name,foundname) report_jobfiles("unknown xml file %q",name) end
local function usexmlfile(name,onlyonce,notext)
startprocessing(name,notext)
@@ -232,7 +253,7 @@ local suffixes = {
local function useanyfile(name,onlyonce)
local s = suffixes[file.suffix(name)]
if s then
- s(file.removesuffix(name),onlyonce)
+ s(removesuffix(name),onlyonce)
else
usetexfile(name,onlyonce) -- e.g. ctx file
--~ resolvers.readfilename(name)
@@ -244,7 +265,7 @@ 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)
+ s(removesuffix(name),onlyonce,notext)
end
end
@@ -429,48 +450,52 @@ job.register('job.structure.collected',root,initialize)
-- component: small unit, either or not components itself
-- product : combination of components
+local context_processfilemany = context.processfilemany
+local context_processfileonce = context.processfileonce
+local context_processfilenone = context.processfilenone
+
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] = { "many", context_processfilemany },
+ -- [v_project] = { "once", context_processfileonce },
+ -- [v_environment] = { "once", context_processfileonce },
+ -- [v_product] = { "once", 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_text] = { "many", context_processfilemany },
+ [v_project] = { "once", context_processfileonce }, -- dubious
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "many", context_processfilemany }, -- dubious
+ [v_component] = { "many", context_processfilemany },
},
[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_text] = { "many", context_processfilemany },
+ [v_project] = { "none", context_processfilenone },
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "none", context_processfilenone },
+ [v_component] = { "none", context_processfilenone },
},
[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_text] = { "many", context_processfilemany },
+ [v_project] = { "none", context_processfilenone },
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "none", context_processfilenone },
+ [v_component] = { "none", context_processfilenone },
},
[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_text] = { "many", context_processfilemany },
+ [v_project] = { "once", context_processfileonce },
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "many", context_processfilemany },
+ [v_component] = { "many", context_processfilemany },
},
[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
+ [v_text] = { "many", context_processfilemany },
+ [v_project] = { "once", context_processfileonce },
+ [v_environment] = { "once", context_processfileonce },
+ [v_product] = { "none", context_processfilenone },
+ [v_component] = { "many", context_processfilemany },
}
}
@@ -531,6 +556,9 @@ local tolerant = false -- too messy, mkii user with the wrong sructure should ad
local function process(what,name)
local depth = #typestack
local process
+ --
+ name = resolvers.resolve(name)
+ --
-- if not tolerant then
-- okay, would be best but not compatible with mkii
process = processors[currenttype][what]
@@ -610,7 +638,7 @@ local function gotonextlevel(what,name) -- todo: something with suffix name
insert(typestack,currenttype)
insert(pathstack,currentpath)
currenttype = what
- currentpath = file.dirname(name)
+ currentpath = dirname(name)
pushtree(what,name)
if start[what] then
start[what]()
@@ -629,10 +657,17 @@ local function gotopreviouslevel(what)
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
+local function autoname(name)
+ if name == "*" then
+ name = nameonly(inputstack[#inputstack] or name)
+ end
+ return name
+end
+
+function commands.startproject (name) gotonextlevel(v_project, autoname(name)) end
+function commands.startproduct (name) gotonextlevel(v_product, autoname(name)) end
+function commands.startcomponent (name) gotonextlevel(v_component, autoname(name)) end
+function commands.startenvironment(name) gotonextlevel(v_environment,autoname(name)) end
function commands.stopproject () gotopreviouslevel(v_project ) end
function commands.stopproduct () gotopreviouslevel(v_product ) end
@@ -673,9 +708,9 @@ end
function commands.loadexamodes(filename)
if not filename or filename == "" then
- filename = file.removesuffix(tex.jobname)
+ filename = removesuffix(tex.jobname)
end
- filename = resolvers.findfile(file.addsuffix(filename,'ctm')) or ""
+ filename = resolvers.findfile(addsuffix(filename,'ctm')) or ""
if filename ~= "" then
report_examodes("loading %s",filename) -- todo: message system
convertexamodes(io.loaddata(filename))
@@ -683,3 +718,196 @@ function commands.loadexamodes(filename)
report_examodes("no mode file %s",filename) -- todo: message system
end
end
+
+-- changed in mtx-context
+-- code moved from luat-ini
+
+-- todo: locals when mtx-context is changed
+
+document = document or {
+ arguments = allocate(),
+ files = allocate(),
+ variables = allocate(), -- for templates
+ options = {
+ commandline = {
+ environments = allocate(),
+ modules = allocate(),
+ modes = allocate(),
+ },
+ ctxfile = {
+ environments = allocate(),
+ modules = allocate(),
+ modes = allocate(),
+ },
+ },
+}
+
+function document.setargument(key,value)
+ document.arguments[key] = value
+end
+
+function document.setdefaultargument(key,default)
+ local v = document.arguments[key]
+ if v == nil or v == "" then
+ document.arguments[key] = default
+ end
+end
+
+function document.setfilename(i,name)
+ if name then
+ document.files[tonumber(i)] = name
+ else
+ document.files[#document.files+1] = tostring(i)
+ end
+end
+
+function document.getargument(key,default) -- commands
+ local v = document.arguments[key]
+ if type(v) == "boolean" then
+ v = (v and "yes") or "no"
+ document.arguments[key] = v
+ end
+ context(v or default or "")
+end
+
+function document.getfilename(i) -- commands
+ context(document.files[i] or "")
+end
+
+function commands.getcommandline() -- has to happen at the tex end in order to expand
+
+ -- the document[arguments|files] tables are copies
+
+ local arguments = document.arguments
+ local files = document.files
+ local options = document.options
+
+ for k, v in next, environment.arguments do
+ k = gsub(k,"^c:","") -- already done, but better be safe than sorry
+ if arguments[k] == nil then
+ arguments[k] = v
+ end
+ end
+
+ -- in the new mtx=context approach we always pass a stub file so we need to
+ -- to trick the files table which actually only has one entry in a tex job
+
+ if arguments.timing then
+ context.usemodule("timing")
+ end
+
+ if arguments.batchmode then
+ context.batchmode(false)
+ end
+
+ if arguments.nonstopmode then
+ context.nonstopmode(false)
+ end
+
+ if arguments.nostatistics then
+ directives.enable("system.nostatistics")
+ end
+
+ if arguments.paranoid then
+ context.setvalue("maxreadlevel",1)
+ end
+
+ if validstring(arguments.path) then
+ context.usepath { arguments.path }
+ end
+
+ local inputfile = validstring(arguments.input)
+
+ if inputfile and dirname(inputfile) == "." and lfs.isfile(inputfile) then
+ -- nicer in checks
+ inputfile = basename(inputfile)
+ end
+
+ context.setupsystem {
+ [constants.directory] = validstring(arguments.setuppath),
+ [constants.inputfile] = inputfile,
+ [constants.file] = validstring(arguments.result),
+ [constants.random] = validstring(arguments.randomseed),
+ [constants.n] = validstring(arguments.kindofrun),
+ [constants.m] = validstring(arguments.currentrun),
+ }
+
+ if validstring(arguments.arguments) then
+ context.setupenv { arguments.arguments }
+ end
+
+ if arguments.once then
+ directives.enable("system.runonce")
+ end
+
+ if arguments.noarrange then
+ context.setuparranging { variables.disable }
+ end
+
+ --
+
+ local commandline = options.commandline
+
+ commandline.environments = table.append(commandline.environments,settings_to_array(validstring(arguments.environment)))
+ commandline.modules = table.append(commandline.modules, settings_to_array(validstring(arguments.usemodule)))
+ commandline.modes = table.append(commandline.modes, settings_to_array(validstring(arguments.mode)))
+
+ --
+
+ if #files == 0 then
+ local list = settings_to_array(validstring(arguments.files))
+ if list and #list > 0 then
+ files = list
+ end
+ end
+
+ if #files == 0 then
+ files = { validstring(arguments.input) }
+ end
+
+ --
+
+ document.arguments = arguments
+ document.files = files
+
+end
+
+-- commandline wins over ctxfile
+
+local function apply(list,action)
+ if list then
+ for i=1,#list do
+ action { list[i] }
+ end
+ end
+end
+
+function commands.setdocumentmodes() -- was setup: *runtime:modes
+ apply(document.options.ctxfile .modes,context.enablemode)
+ apply(document.options.commandline.modes,context.enablemode)
+end
+
+function commands.setdocumentmodules() -- was setup: *runtime:modules
+ apply(document.options.ctxfile .modules,context.usemodule)
+ apply(document.options.commandline.modules,context.usemodule)
+end
+
+function commands.setdocumentenvironments() -- was setup: *runtime:environments
+ apply(document.options.ctxfile .environments,context.environment)
+ apply(document.options.commandline.environments,context.environment)
+end
+
+function commands.logoptions()
+ local arguments = document.arguments
+ local files = document.files
+ write_nl("log","\n% begin of command line arguments\n%\n")
+ for k, v in next, arguments do
+ write_nl("log",format("%% %-20s = %s",k,tostring(v)))
+ end
+ write_nl("log","%\n% end of command line arguments\n")
+ write_nl("log","\n% begin of command line files\n%\n")
+ for i=1,#files do
+ write_nl("log",format("%% %i %s",i,files[i]))
+ end
+ write_nl("log","%\n% end of command line files\n\n")
+end
diff --git a/tex/context/base/file-job.mkvi b/tex/context/base/file-job.mkvi
index 112400cbd..b488ee4eb 100644
--- a/tex/context/base/file-job.mkvi
+++ b/tex/context/base/file-job.mkvi
@@ -75,15 +75,18 @@
\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}}}
+% obsolete, but we keep it as reference of what happened
+%
+% \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
+\ifdefined\textlevel \else \newcount\textlevel \fi % might go away
+\ifdefined\strc_pagenumbers_flush_final_page \else \let\strc_pagenumbers_flush_final_page\relax \fi % ugly
\unexpanded\def\dostarttext
{\glet\dostarttext\relax
@@ -92,8 +95,8 @@
\unexpanded\def\dostoptext
{\glet\dostoptext\relax
- \flushfinallayoutpage % optional
- \page % anyway
+ \strc_pagenumbers_flush_final_page
+ \page % hm, bonus
\the\everystoptext
\global\everystoptext\emptytoks
\the\everybye
@@ -110,6 +113,8 @@
\unexpanded\def\autostarttext{\ctxcommand{autostarttext()}}
\unexpanded\def\autostoptext {\ctxcommand{autostoptext()}}
+\unexpanded\def\finishjob{\stoptext} % nicer in luatex call commandline
+
\newtoks\everystartnotext
\newtoks\everystopnotext
@@ -190,7 +195,7 @@
%D Handy for modules that have a test/demo appended.
-\def\continueifinputfile#name{\doifnot\inputfilename{#name}\endinput}
+\def\continueifinputfile#name{\doifnot\inputfilename{#name}\endinput} % will be lua call ./ check
%def\processifinputfile #name{\doif \inputfilename{#name}}
% \startproject test
@@ -290,6 +295,8 @@
{\setvariables[\s!document][#settings]%
\the\everysetupdocument\relax}
+% metadata:author metadata:title metadata:subject
+
\setvariables
[document]
[\c!before=\directsetup{\s!document:start},
diff --git a/tex/context/base/file-lib.lua b/tex/context/base/file-lib.lua
index 92dacbf5c..c99c2ac41 100644
--- a/tex/context/base/file-lib.lua
+++ b/tex/context/base/file-lib.lua
@@ -33,6 +33,7 @@ function commands.uselibrary(specification) -- todo; reporter
local failure = specification.failure or defaultfailure
local onlyonce = specification.onlyonce
local files = utilities.parsers.settings_to_array(name)
+ local truename = environment.truefilename
local done = false
for i=1,#files do
local filename = files[i]
@@ -42,9 +43,9 @@ function commands.uselibrary(specification) -- todo; reporter
end
for i=1,#patterns do
local somename = format(patterns[i],filename)
-if environment.truefilename then
- somename = environment.truefilename(somename)
-end
+ if truename then
+ somename = truename(somename)
+ end
local foundname = resolvers.getreadfilename("any",".",somename) or ""
if foundname ~= "" then
action(name,foundname)
diff --git a/tex/context/base/file-mod.lua b/tex/context/base/file-mod.lua
index e6592f0f0..4a520e998 100644
--- a/tex/context/base/file-mod.lua
+++ b/tex/context/base/file-mod.lua
@@ -20,14 +20,14 @@ at the <l n='tex'/> side.</p>
local format, concat, tonumber = string.format, table.concat, tonumber
-local trace_modules = false trackers.register("modules.loading", function(v) trace_modules = v end)
+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
+commands = commands or { }
+local commands = commands
-local findbyscheme = resolvers.finders.byscheme -- use different one
+local findbyscheme = resolvers.finders.byscheme -- use different one
-- modules can have a specific suffix or can specify one
@@ -45,7 +45,7 @@ local function usemodule(name,hasscheme)
report_modules("checking url: '%s'",fullname)
end
foundname = resolvers.findtexfile(fullname) or ""
- elseif file.extname(name) ~= "" then
+ elseif file.suffix(name) ~= "" then
if trace_modules then
report_modules("checking file: '%s'",name)
end
@@ -144,8 +144,8 @@ statistics.register("loaded tex modules", function()
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 ""
+ 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
@@ -166,5 +166,5 @@ function commands.doifolderversionelse(one,two) -- one >= two
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)
+ commands.doifelse(one>=two)
end
diff --git a/tex/context/base/file-res.lua b/tex/context/base/file-res.lua
index 4687e140e..6726f71ee 100644
--- a/tex/context/base/file-res.lua
+++ b/tex/context/base/file-res.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['supp-fil'] = {
+if not modules then modules = { } end modules ['file-res'] = {
version = 1.001,
comment = "companion to supp-fil.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -76,9 +76,9 @@ local function readfilename(specification,backtrack,treetoo)
local fname = paths[i] .. "/" .. names[i]
if isfile(fname) then
if trace_files then
- report_files("found on extra path: %s",name)
+ report_files("found on extra path: %s",fname)
end
- fnd = name
+ fnd = fname
break
end
end
diff --git a/tex/context/base/file-syn.lua b/tex/context/base/file-syn.lua
index 1be9fb4b1..8d913bb37 100644
--- a/tex/context/base/file-syn.lua
+++ b/tex/context/base/file-syn.lua
@@ -11,6 +11,9 @@ local report_files = logs.reporter("files")
environment.filesynonyms = environment.filesynonyms or { }
local filesynonyms = environment.filesynonyms
+local settings_to_array = utilities.parsers.settings_to_array
+local findfile = resolvers.findfile
+
storage.register("environment/filesynonyms", filesynonyms, "environment.filesynonyms")
local function truefilename(name)
@@ -37,9 +40,9 @@ function commands.definefilesynonym(name,realname)
end
function commands.definefilefallback(name,alternatives)
- local names = utilities.parser.settings_to_array(alternatives)
+ local names = settings_to_array(alternatives)
for i=1,#names do
- local realname = resolvers.findfile(names[i])
+ local realname = findfile(names[i])
if realname ~= "" then
filesynonyms[name] = realname
break
diff --git a/tex/context/base/font-afk.lua b/tex/context/base/font-afk.lua
new file mode 100644
index 000000000..8b65b0631
--- /dev/null
+++ b/tex/context/base/font-afk.lua
@@ -0,0 +1,200 @@
+if not modules then modules = { } end modules ['font-afk'] = {
+ version = 1.001,
+ comment = "companion to font-afm.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+--[[ldx--
+<p>For ligatures, only characters with a code smaller than 128 make sense,
+anything larger is encoding dependent. An interesting complication is that a
+character can be in an encoding twice but is hashed once.</p>
+--ldx]]--
+
+local allocate = utilities.storage.allocate
+
+fonts.handlers.afm.helpdata = {
+ ligatures = allocate { -- okay, nowadays we could parse the name but type 1 fonts
+ ['f'] = { -- don't have that many ligatures anyway
+ { 'f', 'ff' },
+ { 'i', 'fi' },
+ { 'l', 'fl' },
+ },
+ ['ff'] = {
+ { 'i', 'ffi' }
+ },
+ ['fi'] = {
+ { 'i', 'fii' }
+ },
+ ['fl'] = {
+ { 'i', 'fli' }
+ },
+ ['s'] = {
+ { 't', 'st' }
+ },
+ ['i'] = {
+ { 'j', 'ij' }
+ },
+ },
+ texligatures = allocate {
+ -- ['space'] = {
+ -- { 'L', 'Lslash' },
+ -- { 'l', 'lslash' }
+ -- },
+ -- ['question'] = {
+ -- { 'quoteleft', 'questiondown' }
+ -- },
+ -- ['exclam'] = {
+ -- { 'quoteleft', 'exclamdown' }
+ -- },
+ ['quoteleft'] = {
+ { 'quoteleft', 'quotedblleft' }
+ },
+ ['quoteright'] = {
+ { 'quoteright', 'quotedblright' }
+ },
+ ['hyphen'] = {
+ { 'hyphen', 'endash' }
+ },
+ ['endash'] = {
+ { 'hyphen', 'emdash' }
+ }
+ },
+ leftkerned = allocate {
+ AEligature = "A", aeligature = "a",
+ OEligature = "O", oeligature = "o",
+ IJligature = "I", ijligature = "i",
+ AE = "A", ae = "a",
+ OE = "O", oe = "o",
+ IJ = "I", ij = "i",
+ Ssharp = "S", ssharp = "s",
+ },
+ rightkerned = allocate {
+ AEligature = "E", aeligature = "e",
+ OEligature = "E", oeligature = "e",
+ IJligature = "J", ijligature = "j",
+ AE = "E", ae = "e",
+ OE = "E", oe = "e",
+ IJ = "J", ij = "j",
+ Ssharp = "S", ssharp = "s",
+ },
+ bothkerned = allocate {
+ Acircumflex = "A", acircumflex = "a",
+ Ccircumflex = "C", ccircumflex = "c",
+ Ecircumflex = "E", ecircumflex = "e",
+ Gcircumflex = "G", gcircumflex = "g",
+ Hcircumflex = "H", hcircumflex = "h",
+ Icircumflex = "I", icircumflex = "i",
+ Jcircumflex = "J", jcircumflex = "j",
+ Ocircumflex = "O", ocircumflex = "o",
+ Scircumflex = "S", scircumflex = "s",
+ Ucircumflex = "U", ucircumflex = "u",
+ Wcircumflex = "W", wcircumflex = "w",
+ Ycircumflex = "Y", ycircumflex = "y",
+
+ Agrave = "A", agrave = "a",
+ Egrave = "E", egrave = "e",
+ Igrave = "I", igrave = "i",
+ Ograve = "O", ograve = "o",
+ Ugrave = "U", ugrave = "u",
+ Ygrave = "Y", ygrave = "y",
+
+ Atilde = "A", atilde = "a",
+ Itilde = "I", itilde = "i",
+ Otilde = "O", otilde = "o",
+ Utilde = "U", utilde = "u",
+ Ntilde = "N", ntilde = "n",
+
+ Adiaeresis = "A", adiaeresis = "a", Adieresis = "A", adieresis = "a",
+ Ediaeresis = "E", ediaeresis = "e", Edieresis = "E", edieresis = "e",
+ Idiaeresis = "I", idiaeresis = "i", Idieresis = "I", idieresis = "i",
+ Odiaeresis = "O", odiaeresis = "o", Odieresis = "O", odieresis = "o",
+ Udiaeresis = "U", udiaeresis = "u", Udieresis = "U", udieresis = "u",
+ Ydiaeresis = "Y", ydiaeresis = "y", Ydieresis = "Y", ydieresis = "y",
+
+ Aacute = "A", aacute = "a",
+ Cacute = "C", cacute = "c",
+ Eacute = "E", eacute = "e",
+ Iacute = "I", iacute = "i",
+ Lacute = "L", lacute = "l",
+ Nacute = "N", nacute = "n",
+ Oacute = "O", oacute = "o",
+ Racute = "R", racute = "r",
+ Sacute = "S", sacute = "s",
+ Uacute = "U", uacute = "u",
+ Yacute = "Y", yacute = "y",
+ Zacute = "Z", zacute = "z",
+
+ Dstroke = "D", dstroke = "d",
+ Hstroke = "H", hstroke = "h",
+ Tstroke = "T", tstroke = "t",
+
+ Cdotaccent = "C", cdotaccent = "c",
+ Edotaccent = "E", edotaccent = "e",
+ Gdotaccent = "G", gdotaccent = "g",
+ Idotaccent = "I", idotaccent = "i",
+ Zdotaccent = "Z", zdotaccent = "z",
+
+ Amacron = "A", amacron = "a",
+ Emacron = "E", emacron = "e",
+ Imacron = "I", imacron = "i",
+ Omacron = "O", omacron = "o",
+ Umacron = "U", umacron = "u",
+
+ Ccedilla = "C", ccedilla = "c",
+ Kcedilla = "K", kcedilla = "k",
+ Lcedilla = "L", lcedilla = "l",
+ Ncedilla = "N", ncedilla = "n",
+ Rcedilla = "R", rcedilla = "r",
+ Scedilla = "S", scedilla = "s",
+ Tcedilla = "T", tcedilla = "t",
+
+ Ohungarumlaut = "O", ohungarumlaut = "o",
+ Uhungarumlaut = "U", uhungarumlaut = "u",
+
+ Aogonek = "A", aogonek = "a",
+ Eogonek = "E", eogonek = "e",
+ Iogonek = "I", iogonek = "i",
+ Uogonek = "U", uogonek = "u",
+
+ Aring = "A", aring = "a",
+ Uring = "U", uring = "u",
+
+ Abreve = "A", abreve = "a",
+ Ebreve = "E", ebreve = "e",
+ Gbreve = "G", gbreve = "g",
+ Ibreve = "I", ibreve = "i",
+ Obreve = "O", obreve = "o",
+ Ubreve = "U", ubreve = "u",
+
+ Ccaron = "C", ccaron = "c",
+ Dcaron = "D", dcaron = "d",
+ Ecaron = "E", ecaron = "e",
+ Lcaron = "L", lcaron = "l",
+ Ncaron = "N", ncaron = "n",
+ Rcaron = "R", rcaron = "r",
+ Scaron = "S", scaron = "s",
+ Tcaron = "T", tcaron = "t",
+ Zcaron = "Z", zcaron = "z",
+
+ dotlessI = "I", dotlessi = "i",
+ dotlessJ = "J", dotlessj = "j",
+
+ AEligature = "AE", aeligature = "ae", AE = "AE", ae = "ae",
+ OEligature = "OE", oeligature = "oe", OE = "OE", oe = "oe",
+ IJligature = "IJ", ijligature = "ij", IJ = "IJ", ij = "ij",
+
+ Lstroke = "L", lstroke = "l", Lslash = "L", lslash = "l",
+ Ostroke = "O", ostroke = "o", Oslash = "O", oslash = "o",
+
+ Ssharp = "SS", ssharp = "ss",
+
+ Aumlaut = "A", aumlaut = "a",
+ Eumlaut = "E", eumlaut = "e",
+ Iumlaut = "I", iumlaut = "i",
+ Oumlaut = "O", oumlaut = "o",
+ Uumlaut = "U", uumlaut = "u",
+ }
+}
diff --git a/tex/context/base/font-afm.lua b/tex/context/base/font-afm.lua
index 9d3d8ddd7..dab948b32 100644
--- a/tex/context/base/font-afm.lua
+++ b/tex/context/base/font-afm.lua
@@ -17,12 +17,7 @@ where we handles font encodings. Eventually font encoding goes
away.</p>
--ldx]]--
-local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
-local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
-local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
-local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
-
-local report_afm = logs.reporter("fonts","afm loading")
+local fonts, logs, trackers, containers, resolvers = fonts, logs, trackers, containers, resolvers
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
@@ -30,30 +25,35 @@ 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 = { }
-local pfb = { }
-fonts.handlers.afm = afm
-fonts.handlers.pfb = pfb
+local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
+local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
+local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
-afm.version = 1.410 -- incrementing this number one up will force a re-cache
-afm.cache = containers.define("fonts", "afm", afm.version, true)
-afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
+local report_afm = logs.reporter("fonts","afm loading")
-afm.syncspace = true -- when true, nicer stretch values
-afm.addligatures = true -- best leave this set to true
-afm.addtexligatures = true -- best leave this set to true
-afm.addkerns = true -- best leave this set to true
+local findbinfile = resolvers.findbinfile
local definers = fonts.definers
local readers = fonts.readers
local constructors = fonts.constructors
-local findbinfile = resolvers.findbinfile
+local afm = constructors.newhandler("afm")
+local pfb = constructors.newhandler("pfb")
local afmfeatures = constructors.newfeatures("afm")
local registerafmfeature = afmfeatures.register
+afm.version = 1.410 -- incrementing this number one up will force a re-cache
+afm.cache = containers.define("fonts", "afm", afm.version, true)
+afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
+
+afm.helpdata = { } -- set later on so no local for this
+afm.syncspace = true -- when true, nicer stretch values
+afm.addligatures = true -- best leave this set to true
+afm.addtexligatures = true -- best leave this set to true
+afm.addkerns = true -- best leave this set to true
+
local function setmode(tfmdata,value)
if value then
tfmdata.properties.mode = lower(value)
@@ -429,79 +429,26 @@ end
and extra kerns. This saves quite some lookups later.</p>
--ldx]]--
---[[ldx--
-<p>Only characters with a code smaller than 128 make sense,
-anything larger is encoding dependent. An interesting complication
-is that a character can be in an encoding twice but is hashed
-once.</p>
---ldx]]--
-
-local ligatures = { -- okay, nowadays we could parse the name but type 1 fonts
- ['f'] = { -- don't have that many ligatures anyway
- { 'f', 'ff' },
- { 'i', 'fi' },
- { 'l', 'fl' },
- },
- ['ff'] = {
- { 'i', 'ffi' }
- },
- ['fi'] = {
- { 'i', 'fii' }
- },
- ['fl'] = {
- { 'i', 'fli' }
- },
- ['s'] = {
- { 't', 'st' }
- },
- ['i'] = {
- { 'j', 'ij' }
- },
-}
-
-local texligatures = {
- -- ['space'] = {
- -- { 'L', 'Lslash' },
- -- { 'l', 'lslash' }
- -- },
- -- ['question'] = {
- -- { 'quoteleft', 'questiondown' }
- -- },
- -- ['exclam'] = {
- -- { 'quoteleft', 'exclamdown' }
- -- },
- ['quoteleft'] = {
- { 'quoteleft', 'quotedblleft' }
- },
- ['quoteright'] = {
- { 'quoteright', 'quotedblright' }
- },
- ['hyphen'] = {
- { 'hyphen', 'endash' }
- },
- ['endash'] = {
- { 'hyphen', 'emdash' }
- }
-}
-
local addthem = function(rawdata,ligatures)
- local descriptions = rawdata.descriptions
- local resources = rawdata.resources
- local unicodes = resources.unicodes
- local names = resources.names
- for ligname, ligdata in next, ligatures do
- local one = descriptions[unicodes[ligname]]
- if one then
- for _, pair in next, ligdata do
- local two, three = unicodes[pair[1]], unicodes[pair[2]]
- if two and three then
- local ol = one.ligatures
- if ol then
- if not ol[two] then
- ol[two] = three
+ if ligatures then
+ local descriptions = rawdata.descriptions
+ local resources = rawdata.resources
+ local unicodes = resources.unicodes
+ local names = resources.names
+ for ligname, ligdata in next, ligatures do
+ local one = descriptions[unicodes[ligname]]
+ if one then
+ for _, pair in next, ligdata do
+ local two, three = unicodes[pair[1]], unicodes[pair[2]]
+ if two and three then
+ local ol = one.ligatures
+ if ol then
+ if not ol[two] then
+ ol[two] = three
+ end
+ else
+ one.ligatures = { [two] = three }
end
- else
- one.ligatures = { [two] = three }
end
end
end
@@ -509,8 +456,8 @@ local addthem = function(rawdata,ligatures)
end
end
-addligatures = function(rawdata) addthem(rawdata,ligatures ) end
-addtexligatures = function(rawdata) addthem(rawdata,texligatures) end
+addligatures = function(rawdata) addthem(rawdata,afm.helpdata.ligatures ) end
+addtexligatures = function(rawdata) addthem(rawdata,afm.helpdata.texligatures) end
--[[ldx--
<p>We keep the extra kerns in separate kerning tables so that we can use
@@ -524,208 +471,71 @@ them selectively.</p>
-- we don't use the character database. (Ok, we can have a context specific
-- variant).
--- we can make them numbers
-
-local left = {
- AEligature = "A", aeligature = "a",
- OEligature = "O", oeligature = "o",
- IJligature = "I", ijligature = "i",
- AE = "A", ae = "a",
- OE = "O", oe = "o",
- IJ = "I", ij = "i",
- Ssharp = "S", ssharp = "s",
-}
-
-local right = {
- AEligature = "E", aeligature = "e",
- OEligature = "E", oeligature = "e",
- IJligature = "J", ijligature = "j",
- AE = "E", ae = "e",
- OE = "E", oe = "e",
- IJ = "J", ij = "j",
- Ssharp = "S", ssharp = "s",
-}
-
-local both = {
- Acircumflex = "A", acircumflex = "a",
- Ccircumflex = "C", ccircumflex = "c",
- Ecircumflex = "E", ecircumflex = "e",
- Gcircumflex = "G", gcircumflex = "g",
- Hcircumflex = "H", hcircumflex = "h",
- Icircumflex = "I", icircumflex = "i",
- Jcircumflex = "J", jcircumflex = "j",
- Ocircumflex = "O", ocircumflex = "o",
- Scircumflex = "S", scircumflex = "s",
- Ucircumflex = "U", ucircumflex = "u",
- Wcircumflex = "W", wcircumflex = "w",
- Ycircumflex = "Y", ycircumflex = "y",
-
- Agrave = "A", agrave = "a",
- Egrave = "E", egrave = "e",
- Igrave = "I", igrave = "i",
- Ograve = "O", ograve = "o",
- Ugrave = "U", ugrave = "u",
- Ygrave = "Y", ygrave = "y",
-
- Atilde = "A", atilde = "a",
- Itilde = "I", itilde = "i",
- Otilde = "O", otilde = "o",
- Utilde = "U", utilde = "u",
- Ntilde = "N", ntilde = "n",
-
- Adiaeresis = "A", adiaeresis = "a", Adieresis = "A", adieresis = "a",
- Ediaeresis = "E", ediaeresis = "e", Edieresis = "E", edieresis = "e",
- Idiaeresis = "I", idiaeresis = "i", Idieresis = "I", idieresis = "i",
- Odiaeresis = "O", odiaeresis = "o", Odieresis = "O", odieresis = "o",
- Udiaeresis = "U", udiaeresis = "u", Udieresis = "U", udieresis = "u",
- Ydiaeresis = "Y", ydiaeresis = "y", Ydieresis = "Y", ydieresis = "y",
-
- Aacute = "A", aacute = "a",
- Cacute = "C", cacute = "c",
- Eacute = "E", eacute = "e",
- Iacute = "I", iacute = "i",
- Lacute = "L", lacute = "l",
- Nacute = "N", nacute = "n",
- Oacute = "O", oacute = "o",
- Racute = "R", racute = "r",
- Sacute = "S", sacute = "s",
- Uacute = "U", uacute = "u",
- Yacute = "Y", yacute = "y",
- Zacute = "Z", zacute = "z",
-
- Dstroke = "D", dstroke = "d",
- Hstroke = "H", hstroke = "h",
- Tstroke = "T", tstroke = "t",
-
- Cdotaccent = "C", cdotaccent = "c",
- Edotaccent = "E", edotaccent = "e",
- Gdotaccent = "G", gdotaccent = "g",
- Idotaccent = "I", idotaccent = "i",
- Zdotaccent = "Z", zdotaccent = "z",
-
- Amacron = "A", amacron = "a",
- Emacron = "E", emacron = "e",
- Imacron = "I", imacron = "i",
- Omacron = "O", omacron = "o",
- Umacron = "U", umacron = "u",
-
- Ccedilla = "C", ccedilla = "c",
- Kcedilla = "K", kcedilla = "k",
- Lcedilla = "L", lcedilla = "l",
- Ncedilla = "N", ncedilla = "n",
- Rcedilla = "R", rcedilla = "r",
- Scedilla = "S", scedilla = "s",
- Tcedilla = "T", tcedilla = "t",
-
- Ohungarumlaut = "O", ohungarumlaut = "o",
- Uhungarumlaut = "U", uhungarumlaut = "u",
-
- Aogonek = "A", aogonek = "a",
- Eogonek = "E", eogonek = "e",
- Iogonek = "I", iogonek = "i",
- Uogonek = "U", uogonek = "u",
-
- Aring = "A", aring = "a",
- Uring = "U", uring = "u",
-
- Abreve = "A", abreve = "a",
- Ebreve = "E", ebreve = "e",
- Gbreve = "G", gbreve = "g",
- Ibreve = "I", ibreve = "i",
- Obreve = "O", obreve = "o",
- Ubreve = "U", ubreve = "u",
-
- Ccaron = "C", ccaron = "c",
- Dcaron = "D", dcaron = "d",
- Ecaron = "E", ecaron = "e",
- Lcaron = "L", lcaron = "l",
- Ncaron = "N", ncaron = "n",
- Rcaron = "R", rcaron = "r",
- Scaron = "S", scaron = "s",
- Tcaron = "T", tcaron = "t",
- Zcaron = "Z", zcaron = "z",
-
- dotlessI = "I", dotlessi = "i",
- dotlessJ = "J", dotlessj = "j",
-
- AEligature = "AE", aeligature = "ae", AE = "AE", ae = "ae",
- OEligature = "OE", oeligature = "oe", OE = "OE", oe = "oe",
- IJligature = "IJ", ijligature = "ij", IJ = "IJ", ij = "ij",
-
- Lstroke = "L", lstroke = "l", Lslash = "L", lslash = "l",
- Ostroke = "O", ostroke = "o", Oslash = "O", oslash = "o",
-
- Ssharp = "SS", ssharp = "ss",
-
- Aumlaut = "A", aumlaut = "a",
- Eumlaut = "E", eumlaut = "e",
- Iumlaut = "I", iumlaut = "i",
- Oumlaut = "O", oumlaut = "o",
- Uumlaut = "U", uumlaut = "u",
-
-}
-
addkerns = function(rawdata) -- using shcodes is not robust here
local descriptions = rawdata.descriptions
local resources = rawdata.resources
local unicodes = resources.unicodes
local function do_it_left(what)
- for unicode, description in next, descriptions do
- local kerns = description.kerns
- if kerns then
- local extrakerns
- for complex, simple in next, what do
- complex = unicodes[complex]
- simple = unicodes[simple]
- if complex and simple then
- local ks = kerns[simple]
- if ks and not kerns[complex] then
- if extrakerns then
- extrakerns[complex] = ks
- else
- extrakerns = { [complex] = ks }
+ if what then
+ for unicode, description in next, descriptions do
+ local kerns = description.kerns
+ if kerns then
+ local extrakerns
+ for complex, simple in next, what do
+ complex = unicodes[complex]
+ simple = unicodes[simple]
+ if complex and simple then
+ local ks = kerns[simple]
+ if ks and not kerns[complex] then
+ if extrakerns then
+ extrakerns[complex] = ks
+ else
+ extrakerns = { [complex] = ks }
+ end
end
end
end
- end
- if extrakerns then
- description.extrakerns = extrakerns
+ if extrakerns then
+ description.extrakerns = extrakerns
+ end
end
end
end
end
local function do_it_copy(what)
- for complex, simple in next, what do
- complex = unicodes[complex]
- simple = unicodes[simple]
- if complex and simple then
- local complexdescription = descriptions[complex]
- if complexdescription then -- optional
- local simpledescription = descriptions[complex]
- if simpledescription then
- local extrakerns
- local kerns = simpledescription.kerns
- if kerns then
- for unicode, kern in next, kerns do
- if extrakerns then
- extrakerns[unicode] = kern
- else
- extrakerns = { [unicode] = kern }
+ if what then
+ for complex, simple in next, what do
+ complex = unicodes[complex]
+ simple = unicodes[simple]
+ if complex and simple then
+ local complexdescription = descriptions[complex]
+ if complexdescription then -- optional
+ local simpledescription = descriptions[complex]
+ if simpledescription then
+ local extrakerns
+ local kerns = simpledescription.kerns
+ if kerns then
+ for unicode, kern in next, kerns do
+ if extrakerns then
+ extrakerns[unicode] = kern
+ else
+ extrakerns = { [unicode] = kern }
+ end
end
end
- end
- local extrakerns = simpledescription.extrakerns
- if extrakerns then
- for unicode, kern in next, extrakerns do
- if extrakerns then
- extrakerns[unicode] = kern
- else
- extrakerns = { [unicode] = kern }
+ local extrakerns = simpledescription.extrakerns
+ if extrakerns then
+ for unicode, kern in next, extrakerns do
+ if extrakerns then
+ extrakerns[unicode] = kern
+ else
+ extrakerns = { [unicode] = kern }
+ end
end
end
- end
- if extrakerns then
- complexdescription.extrakerns = extrakerns
+ if extrakerns then
+ complexdescription.extrakerns = extrakerns
+ end
end
end
end
@@ -733,11 +543,11 @@ addkerns = function(rawdata) -- using shcodes is not robust here
end
end
-- add complex with values of simplified when present
- do_it_left(left)
- do_it_left(both)
+ do_it_left(afm.helpdata.leftkerned)
+ do_it_left(afm.helpdata.bothkerned)
-- copy kerns from simple char to complex char unless set
- do_it_copy(both)
- do_it_copy(right)
+ do_it_copy(afm.helpdata.bothkerned)
+ do_it_copy(afm.helpdata.rightkerned)
end
--[[ldx--
diff --git a/tex/context/base/font-age.lua b/tex/context/base/font-age.lua
index 741bb475a..36647c3a6 100644
--- a/tex/context/base/font-age.lua
+++ b/tex/context/base/font-age.lua
@@ -4,6 +4,7 @@ if not modules then modules = { } end modules ['font-age'] = {
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "derived from http://www.adobe.com/devnet/opentype/archives/glyphlist.txt",
original = "Adobe Glyph List, version 2.0, September 20, 2002",
+ dataonly = true,
}
if context then
diff --git a/tex/context/base/font-agl.lua b/tex/context/base/font-agl.lua
index 6c1f387ba..ca7fb61cb 100644
--- a/tex/context/base/font-agl.lua
+++ b/tex/context/base/font-agl.lua
@@ -271,7 +271,7 @@ for a, u in next, extras do
end
end
--- We load this table only when needed. We coul duse a loading mechanism
+-- We load this table only when needed. We could use a loading mechanism
-- return the table but there are no more vectors like this so why bother.
fonts.encodings = fonts.encodings or { }
diff --git a/tex/context/base/font-aux.lua b/tex/context/base/font-aux.lua
index 0396554ad..5e938ceb9 100644
--- a/tex/context/base/font-aux.lua
+++ b/tex/context/base/font-aux.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['font-aux'] = {
license = "see context related readme files"
}
-local number = tonumber
+local tonumber, type = tonumber, type
local wrap, yield = coroutine.wrap, coroutine.yield
local fonts, font = fonts, font
diff --git a/tex/context/base/font-aux.mkvi b/tex/context/base/font-aux.mkvi
new file mode 100644
index 000000000..bd655e41c
--- /dev/null
+++ b/tex/context/base/font-aux.mkvi
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=font-gds,
+%D version=2012.06.26,
+%D title=\CONTEXT\ Font Support,
+%D subtitle=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 Font Support / Helpers}
+
+%D Here we collect code moved from other files, like some of the
+%D support modules.
+
+\unprotect
+
+%D Leftovers:
+
+\unexpanded\def\xbox {\bgroup\aftergroup\egroup\hbox\bgroup\tx \let\next=}
+\unexpanded\def\xxbox{\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=}
+
+\protect \endinput
diff --git a/tex/context/base/font-chk.lua b/tex/context/base/font-chk.lua
index 04b49b02c..7536a3e09 100644
--- a/tex/context/base/font-chk.lua
+++ b/tex/context/base/font-chk.lua
@@ -149,7 +149,7 @@ 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
local cache = { } -- saves some tables but not that impressive
-local function addmissingsymbols(tfmdata)
+local function addmissingsymbols(tfmdata) -- we can have an alternative with rules
local characters = tfmdata.characters
local size = tfmdata.parameters.size
local privates = tfmdata.properties.privates
diff --git a/tex/context/base/font-chk.mkiv b/tex/context/base/font-chk.mkiv
new file mode 100644
index 000000000..d436388de
--- /dev/null
+++ b/tex/context/base/font-chk.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=font-chk,
+%D version=2009.01.02, % moved from font-tra
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=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.
+
+\writestatus{loading}{ConTeXt Font Macros / Checking}
+
+\registerctxluafile{font-chk}{1.001}
+
+\unexpanded\def\checkcharactersinfont {\ctxcommand{checkcharactersinfont()}}
+\unexpanded\def\removemissingcharacters {\ctxcommand{removemissingcharacters()}}
+\unexpanded\def\replacemissingcharacters{\ctxcommand{replacemissingcharacters()}}
+
+\endinput
diff --git a/tex/context/base/font-cid.lua b/tex/context/base/font-cid.lua
index 4a4c4d209..bf186d885 100644
--- a/tex/context/base/font-cid.lua
+++ b/tex/context/base/font-cid.lua
@@ -10,17 +10,17 @@ local format, match, lower = string.format, string.match, string.lower
local tonumber = tonumber
local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match
-local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+local fonts, logs, trackers = fonts, logs, trackers
-local report_otf = logs.reporter("fonts","otf loading")
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
-local fonts = fonts
+local report_otf = logs.reporter("fonts","otf loading")
-local cid = { }
-fonts.cid = cid
+local cid = { }
+fonts.cid = cid
-local cidmap = { }
-local cidmax = 10
+local cidmap = { }
+local cidmax = 10
-- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap
--
@@ -79,8 +79,7 @@ local function loadcidfile(filename)
end
end
-cid.loadfile = loadcidfile -- we use the frozen variant
-
+cid.loadfile = loadcidfile -- we use the frozen variant
local template = "%s-%s-%s.cidmap"
local function locate(registry,ordering,supplement)
diff --git a/tex/context/base/font-col.lua b/tex/context/base/font-col.lua
index f8add1e4e..4b96cca31 100644
--- a/tex/context/base/font-col.lua
+++ b/tex/context/base/font-col.lua
@@ -8,32 +8,40 @@ if not modules then modules = { } end modules ['font-col'] = {
-- possible optimization: delayed initialization of vectors
-local gmatch, type = string.gmatch, type
-local traverse_id = node.traverse_id
-local lpegmatch = lpeg.match
+local context, commands, trackers, logs = context, commands, trackers, logs
+local node, nodes, fonts, characters = node, nodes, fonts, characters
+local file, lpeg, table, string = file, lpeg, table, string
+
+local type, next, toboolean = type, next, toboolean
+local gmatch = string.gmatch
local fastcopy = table.fastcopy
-local settings_to_hash = utilities.parsers.settings_to_hash
+----- P, Cc, lpegmatch = lpeg.P, lpeg.Cc, lpeg.match
+
+local traverse_id = node.traverse_id
+local settings_to_hash = utilities.parsers.settings_to_hash
-local trace_collecting = false trackers.register("fonts.collecting", function(v) trace_collecting = v end)
+local trace_collecting = false trackers.register("fonts.collecting", function(v) trace_collecting = v end)
-local report_fonts = logs.reporter("fonts","collections")
+local report_fonts = logs.reporter("fonts","collections")
-local fonts, context = fonts, context
+fonts.collections = fonts.collections or { }
+local collections = fonts.collections
-fonts.collections = fonts.collections or { }
-local collections = fonts.collections
+collections.definitions = collections.definitions or { }
+local definitions = collections.definitions
-collections.definitions = collections.definitions or { }
-local definitions = collections.definitions
+collections.vectors = collections.vectors or { }
+local vectors = collections.vectors
-collections.vectors = collections.vectors or { }
-local vectors = collections.vectors
+local fontdata = fonts.hashes.identifiers
-local fontdata = fonts.hashes.identifiers
+local glyph_code = nodes.nodecodes.glyph
-local glyph = node.id('glyph')
+local fontpatternhassize = fonts.helpers.fontpatternhassize
-local list, current, active = { }, 0, false
+local list = { }
+local current = 0
+local enabled = false
-- maybe also a copy
@@ -145,17 +153,19 @@ function collections.clonevector(name)
if trace_collecting then
report_fonts("def: activating collection %s for font %s",name,current)
end
- active = true
+ if not enabled then
+ nodes.tasks.enableaction("processors","fonts.collections.process")
+ enabled = true
+ end
statistics.stoptiming(fonts)
end
-- we already have this parser
-
-local P, Cc = lpeg.P, lpeg.Cc
-local spec = (P("sa") + P("at") + P("scaled") + P("at") + P("mo")) * P(" ")^1 * (1-P(" "))^1 * P(" ")^0 * -1
-local okay = ((1-spec)^1 * spec * Cc(true)) + Cc(false)
-
--- todo: check for already done
+--
+-- local spec = (P("sa") + P("at") + P("scaled") + P("at") + P("mo")) * P(" ")^1 * (1-P(" "))^1 * P(" ")^0 * -1
+-- local okay = ((1-spec)^1 * spec * Cc(true)) + Cc(false)
+--
+-- if lpegmatch(okay,name) then
function collections.prepare(name)
current = font.current()
@@ -175,7 +185,7 @@ function collections.prepare(name)
local f = d[i]
local name = f.font
local scale = f.rscale or 1
- if lpegmatch(okay,name) then
+ if fontpatternhassize(name) then
context.font_fallbacks_clone_unique(name,scale)
else
context.font_fallbacks_clone_inherited(name,scale)
@@ -198,32 +208,28 @@ function collections.report(message)
end
function collections.process(head) -- this way we keep feature processing
- if active then
- local done = false
- for n in traverse_id(glyph,head) do
- local v = vectors[n.font]
- if v then
- local id = v[n.char]
- if id then
- if type(id) == "table" then
- local newid, newchar = id[1], id[2]
- if trace_collecting then
- report_fonts("lst: remapping character %s in font %s to character %s in font %s",n.char,n.font,newchar,newid)
- end
- n.font, n.char = newid, newchar
- else
- if trace_collecting then
- report_fonts("lst: remapping font %s to %s for character %s",n.font,id,n.char)
- end
- n.font = id
+ local done = false
+ for n in traverse_id(glyph_code,head) do
+ local v = vectors[n.font]
+ if v then
+ local id = v[n.char]
+ if id then
+ if type(id) == "table" then
+ local newid, newchar = id[1], id[2]
+ if trace_collecting then
+ report_fonts("lst: remapping character %s in font %s to character %s in font %s",n.char,n.font,newchar,newid)
end
+ n.font, n.char = newid, newchar
+ else
+ if trace_collecting then
+ report_fonts("lst: remapping font %s to %s for character %s",n.font,id,n.char)
+ end
+ n.font = id
end
end
end
- return head, done
- else
- return head, false
end
+ return head, done
end
-- interface
diff --git a/tex/context/base/font-con.lua b/tex/context/base/font-con.lua
index 928099688..6074bab18 100644
--- a/tex/context/base/font-con.lua
+++ b/tex/context/base/font-con.lua
@@ -29,9 +29,9 @@ local report_defining = logs.reporter("fonts","defining")
--ldx]]--
local fonts = fonts
-local constructors = { }
+local constructors = fonts.constructors or { }
fonts.constructors = constructors
-local handlers = { }
+local handlers = fonts.handlers or { } -- can have preloaded tables
fonts.handlers = handlers
local specifiers = fonts.specifiers
@@ -358,6 +358,10 @@ function constructors.scale(tfmdata,specification)
elseif forcedsize > 1000 then -- safeguard
scaledpoints = forcedsize
end
+ targetparameters.mathsize = mathsize -- context specific
+ targetparameters.textsize = textsize -- context specific
+ targetparameters.forcedsize = forcedsize -- context specific
+ targetparameters.extrafactor = extrafactor -- context specific
--
local tounicode = resources.tounicode
local defaultwidth = resources.defaultwidth or 0
@@ -1069,7 +1073,7 @@ setmetatableindex(formats, function(t,k)
t[k] = l
return l
end
- return rawget(t,file.extname(l))
+ return rawget(t,file.suffix(l))
end)
local locations = { }
@@ -1166,19 +1170,31 @@ function constructors.getfeatureaction(what,where,mode,name)
end
end
-function constructors.newfeatures(what)
- local features = handlers[what].features
+function constructors.newhandler(what) -- could be a metatable newindex
+ local handler = handlers[what]
+ if not handler then
+ handler = { }
+ handlers[what] = handler
+ end
+ return handler
+end
+
+function constructors.newfeatures(what) -- could be a metatable newindex
+ local handler = handlers[what]
+ local features = handler.features
if not features then
- local tables = handlers[what].tables -- can be preloaded
+ local tables = handler.tables -- can be preloaded
+ local statistics = handler.statistics -- can be preloaded
features = allocate {
defaults = { },
descriptions = tables and tables.features or { },
+ used = statistics and statistics.usedfeatures or { },
initializers = { base = { }, node = { } },
processors = { base = { }, node = { } },
manipulators = { base = { }, node = { } },
}
features.register = function(specification) return register(features,specification) end
- handlers[what].features = features -- will also become hidden
+ handler.features = features -- will also become hidden
end
return features
end
diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua
index 4b324a6db..1b3384833 100644
--- a/tex/context/base/font-ctx.lua
+++ b/tex/context/base/font-ctx.lua
@@ -8,6 +8,11 @@ if not modules then modules = { } end modules ['font-ctx'] = {
-- At some point I will clean up the code here so that at the tex end
-- the table interface is used.
+--
+-- Todo: make a proper 'next id' mechanism (register etc) or wait till 'true'
+-- in virtual fonts indices is implemented.
+
+local context, commands = context, commands
local texcount, texsetcount = tex.count, tex.setcount
local format, gmatch, match, find, lower, gsub, byte = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub, string.byte
@@ -53,7 +58,7 @@ local texattribute = tex.attribute
local designsizefilename = fontgoodies.designsizes.filename
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = handlers.otf.features
local registerotffeature = otffeatures.register
local baseprocessors = otffeatures.processors.base
local baseinitializers = otffeatures.initializers.base
@@ -141,10 +146,11 @@ 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 markdata = allocate()
local italicsdata = allocate()
+local lastmathids = allocate()
hashes.characters = chardata
hashes.descriptions = descriptions
@@ -152,74 +158,113 @@ hashes.parameters = parameters
hashes.properties = properties
hashes.resources = resources
hashes.quads = quaddata
-hashes.marks = markdata
+hashes.emwidths = quaddata
hashes.xheights = xheightdata
+hashes.exheights = xheightdata
hashes.csnames = csnames
+hashes.marks = markdata
hashes.italics = italicsdata
+hashes.lastmathids = lastmathids
-setmetatableindex(chardata, function(t,k)
- local characters = fontdata[k].characters
- t[k] = characters
- return characters
+setmetatableindex(chardata, function(t,k)
+ if k == true then
+ return chardata[currentfont()]
+ else
+ local characters = fontdata[k].characters
+ t[k] = characters
+ return characters
+ end
end)
-setmetatableindex(descriptions, function(t,k)
- local descriptions = fontdata[k].descriptions
- t[k] = descriptions
- return descriptions
+setmetatableindex(descriptions, function(t,k)
+ if k == true then
+ return descriptions[currentfont()]
+ else
+ local descriptions = fontdata[k].descriptions
+ t[k] = descriptions
+ return descriptions
+ end
end)
setmetatableindex(parameters, function(t,k)
- local parameters = fontdata[k].parameters
- t[k] = parameters
- return parameters
+ if k == true then
+ return parameters[currentfont()]
+ else
+ local parameters = fontdata[k].parameters
+ t[k] = parameters
+ return parameters
+ end
end)
setmetatableindex(properties, function(t,k)
- local properties = fontdata[k].properties
- t[k] = properties
- return properties
+ if k == true then
+ return properties[currentfont()]
+ else
+ local properties = fontdata[k].properties
+ t[k] = properties
+ return properties
+ end
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
+ if k == true then
+ return resources[currentfont()]
+ else
+ 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
end)
setmetatableindex(quaddata, function(t,k)
- local parameters = parameters[k]
- local quad = parameters and parameters.quad or 0
- t[k] = quad
- return quad
+ if k == true then
+ return quaddata[currentfont()]
+ else
+ local parameters = parameters[k]
+ local quad = parameters and parameters.quad or 0
+ t[k] = quad
+ return quad
+ end
end)
setmetatableindex(markdata, function(t,k)
- local resources = fontdata[k].resources or { }
- local marks = resources.marks or { }
- t[k] = marks
- return marks
+ if k == true then
+ return markdata[currentfont()]
+ else
+ local resources = fontdata[k].resources or { }
+ local marks = resources.marks or { }
+ t[k] = marks
+ return marks
+ end
end)
setmetatableindex(xheightdata, function(t,k)
- local parameters = parameters[k]
- local xheight = parameters and parameters.xheight or 0
- t[k] = xheight
- return quad
+ if k == true then
+ return xheightdata[currentfont()]
+ else
+ local parameters = parameters[k]
+ local xheight = parameters and parameters.xheight or 0
+ t[k] = xheight
+ return xheight
+ end
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
+ if k == true then
+ return italicsdata[currentfont()]
else
- hasitalics = false
+ 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
- t[k] = hasitalics
- return hasitalics
end)
-- this cannot be a feature initializer as there is no auto namespace
@@ -750,6 +795,18 @@ local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- value
local sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_scaled + scale_none)
local splitpattern = spaces * value * spaces * rest
+function helpers.splitfontpattern(str)
+ local name, size = lpegmatch(splitpattern,str)
+ local kind, size = lpegmatch(sizepattern,size)
+ return name, kind, size
+end
+
+function helpers.fontpatternhassize(str)
+ local name, size = lpegmatch(splitpattern,str)
+ local kind, size = lpegmatch(sizepattern,size)
+ return size or false
+end
+
local specification -- still needed as local ?
local getspecification = definers.getspecification
@@ -761,6 +818,7 @@ local setdefaultfontname = context.fntsetdefname
local setsomefontname = context.fntsetsomename
local setemptyfontsize = context.fntsetnopsize
local setsomefontsize = context.fntsetsomesize
+local letvaluerelax = context.letvaluerelax
function commands.definefont_one(str)
statistics.starttiming(fonts)
@@ -905,10 +963,12 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature
end
end
local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?)
+ --
+ local lastfontid = 0
if not tfmdata then
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
+ lastfontid = -1
+ 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, designsize: %s/%s)",
@@ -918,14 +978,13 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature
tex.definefont(global,cs,tfmdata)
-- resolved (when designsize is used):
setsomefontsize(fontdata[tfmdata].parameters.size .. "sp")
- texsetcount("global","lastfontid",tfmdata)
+ lastfontid = tfmdata
else
-- setting the extra characters will move elsewhere
local characters = tfmdata.characters
local parameters = tfmdata.parameters
- -- we use char0 as signal
+ -- we use char0 as signal; cf the spec pdf can handle this (no char in slot)
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
@@ -943,15 +1002,22 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature
end
-- resolved (when designsize is used):
setsomefontsize((tfmdata.parameters.size or 655360) .. "sp")
- --~ if specification.fallbacks then
- --~ fonts.collections.prepare(specification.fallbacks)
- --~ end
- texsetcount("global","lastfontid",id)
+ lastfontid = id
end
if trace_defining then
report_defining("memory usage after: %s",statistics.memused())
report_defining("stop stage two")
end
+ --
+ texsetcount("global","lastfontid",lastfontid)
+ if not mathsize then
+ -- forget about it
+ elseif mathsize == 0 then
+ lastmathids[1] = lastfontid
+ else
+ lastmathids[mathsize] = lastfontid
+ end
+ --
statistics.stoptiming(fonts)
end
@@ -1384,7 +1450,8 @@ function helpers.dimenfactor(unit,tfmdata) -- could be a method of a font instan
elseif unit == "em" then
return (tfmdata and tfmdata.parameters.em_width) or 655360
else
- return dimenfactors[unit] or unit
+ local du = dimenfactors[unit]
+ return du and 1/du or tonumber(unit) or 1
end
end
@@ -1541,3 +1608,106 @@ commands.definefontfeature = fonts.specifiers.presetcontext
function commands.featurelist(...)
context(fonts.specifiers.contexttostring(...))
end
+
+-- a fontkern plug:
+
+local copy_node = node.copy
+local kern = nodes.pool.register(nodes.pool.kern())
+
+node.set_attribute(kern,attributes.private('fontkern'),1) -- we can have several, attributes are shared
+
+nodes.injections.installnewkern(function(k)
+ local c = copy_node(kern)
+ c.kern = k
+ return c
+end)
+
+directives.register("nodes.injections.fontkern", function(v) kern.subtype = v and 0 or 1 end)
+
+-- here
+
+local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end)
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local analyzers = fonts.analyzers
+local methods = analyzers.methods
+
+local get_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+local unset_attribute = node.unset_attribute
+local traverse_by_id = node.traverse_id
+
+local a_color = attributes.private('color')
+local a_colormodel = attributes.private('colormodel')
+local a_state = attributes.private('state')
+local m_color = attributes.list[a_color] or { }
+
+local glyph_code = nodes.nodecodes.glyph
+
+local names = {
+ "font:1", "font:2", "font:3", "font:3", -- arabic
+ "font:4", "font:5", "font:6", "font:7", "font:8", "font:9", -- devanagary
+}
+
+local function markstates(head)
+ if head then
+ local model = get_attribute(head,a_colormodel) or 1
+ for glyph in traverse_by_id(glyph_code,head) do
+ local a = get_attribute(glyph,a_state)
+ if a then
+ local name = names[a]
+ if name then
+ local color = m_color[name]
+ if color then
+ set_attribute(glyph,a_colormodel,model)
+ set_attribute(glyph,a_color,color)
+ end
+ end
+ end
+ end
+ end
+end
+
+local function analyzeprocessor(head,font,attr)
+ local tfmdata = fontdata[font]
+ local script, language = otf.scriptandlanguage(tfmdata,attr)
+ local action = methods[script]
+ if not action then
+ return head, false
+ end
+ if type(action) == "function" then
+ local head, done = action(head,font,attr)
+ if done and trace_analyzing then
+ markstates(head)
+ end
+ return head, done
+ end
+ action = action[language]
+ if action then
+ local head, done = action(head,font,attr)
+ if done and trace_analyzing then
+ markstates(head)
+ end
+ return head, done
+ else
+ return head, false
+ end
+end
+
+registerotffeature { -- adapts
+ name = "analyze",
+ processors = {
+ node = analyzeprocessor,
+ }
+}
+
+function methods.nocolor(head,font,attr)
+ for n in traverse_by_id(glyph_code,head) do
+ if not font or n.font == font then
+ unset_attribute(n,a_color)
+ end
+ end
+ return head, true
+end
diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua
index 96de480ac..864e5bd16 100644
--- a/tex/context/base/font-def.lua
+++ b/tex/context/base/font-def.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['font-def'] = {
license = "see context related readme files"
}
+-- We can overload some of the definers.functions so we don't local them.
+
local concat = table.concat
local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub
local tostring, next = tostring, next
@@ -42,7 +44,6 @@ definers.methods = definers.methods or { }
local internalized = allocate() -- internal tex numbers (private)
-
local loadedfonts = constructors.loadedfonts
local designsizes = constructors.designsizes
@@ -72,7 +73,7 @@ and prepares a table that will move along as we proceed.</p>
-- name name(sub) name(sub)*spec name*spec
-- name@spec*oeps
-local splitter, splitspecifiers = nil, ""
+local splitter, splitspecifiers = nil, "" -- not so nice
local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc
@@ -83,7 +84,7 @@ local space = P(" ")
definers.defaultlookup = "file"
-local prefixpattern = P(false)
+local prefixpattern = P(false)
local function addspecifier(symbol)
splitspecifiers = splitspecifiers .. symbol
@@ -119,12 +120,12 @@ function definers.registersplit(symbol,action,verbosename)
end
end
-function definers.makespecification(specification,lookup,name,sub,method,detail,size)
+local function 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",
- specification, (lookup ~= "" and lookup) or "[file]", (name ~= "" and name) or "-",
- (sub ~= "" and sub) or "-", (method ~= "" and method) or "-", (detail ~= "" and detail) or "-")
+ specification, lookup ~= "" and lookup or "[file]", name ~= "" and name or "-",
+ sub ~= "" and sub or "-", method ~= "" and method or "-", detail ~= "" and detail or "-")
end
if not lookup or lookup == "" then
lookup = definers.defaultlookup
@@ -144,10 +145,13 @@ function definers.makespecification(specification,lookup,name,sub,method,detail,
return t
end
+
+definers.makespecification = makespecification
+
function definers.analyze(specification, size)
-- can be optimized with locals
local lookup, name, sub, method, detail = getspecification(specification or "")
- return definers.makespecification(specification, lookup, name, sub, method, detail, size)
+ return makespecification(specification, lookup, name, sub, method, detail, size)
end
--[[ldx--
@@ -194,7 +198,7 @@ function resolvers.spec(specification)
if resolved then
specification.resolved = resolved
specification.sub = sub
- specification.forced = file.extname(resolved)
+ specification.forced = file.suffix(resolved)
specification.name = file.removesuffix(resolved)
end
else
@@ -242,12 +246,13 @@ specification yet.</p>
function definers.applypostprocessors(tfmdata)
local postprocessors = tfmdata.postprocessors
if postprocessors then
+ local properties = tfmdata.properties
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)
+ properties.fullname = format("%s-%s",properties.fullname,extrahash)
end
end
end
diff --git a/tex/context/base/font-ext.lua b/tex/context/base/font-ext.lua
index 331ffbdfa..560cf23ee 100644
--- a/tex/context/base/font-ext.lua
+++ b/tex/context/base/font-ext.lua
@@ -10,7 +10,9 @@ local utf = unicode.utf8
local next, type, byte = next, type, string.byte
local gmatch, concat, format = string.gmatch, table.concat, string.format
local utfchar = utf.char
-local getparameters = utilities.parsers.getparameters
+
+local commands, context = commands, context
+local fonts, utilities = fonts, utilities
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)
@@ -26,17 +28,18 @@ will depend of the font format. Here we define the few that are kind
of neutral.</p>
--ldx]]--
-local fonts = fonts
-local fontdata = fonts.hashes.identifiers
+local handlers = fonts.handlers
+local hashes = fonts.hashes
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
-local afmfeatures = fonts.constructors.newfeatures("afm")
-local registerafmfeature = afmfeatures.register
+local fontdata = hashes.identifiers
local allocate = utilities.storage.allocate
local settings_to_array = utilities.parsers.settings_to_array
+local getparameters = utilities.parsers.getparameters
+
local setmetatableindex = table.setmetatableindex
-- -- -- -- -- --
@@ -62,14 +65,15 @@ end
-- expansion (hz)
-- -- -- -- -- --
-fonts.expansions = allocate()
-local expansions = fonts.expansions
+local expansions = fonts.expansions or allocate()
-expansions.classes = allocate()
-local classes = expansions.classes
+fonts.expansions = expansions
-expansions.vectors = allocate()
-local vectors = expansions.vectors
+local classes = expansions.classes or allocate()
+local vectors = expansions.vectors or allocate()
+
+expansions.classes = classes
+expansions.vectors = vectors
-- beware, pdftex itself uses percentages * 10
@@ -880,8 +884,8 @@ 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 properties = tfmdata.properties
+ local privates = properties.privates
local lastprivate = properties.lastprivate
if lastprivate then
lastprivate = lastprivate + 1
@@ -903,7 +907,7 @@ end
function fonts.helpers.getprivatenode(tfmdata,name)
local properties = tfmdata.properties
- local privates = properties and properties.privates
+ local privates = properties and properties.privates
if privates then
local p = privates[name]
if p then
@@ -925,7 +929,7 @@ end
function fonts.helpers.hasprivate(tfmdata,name)
local properties = tfmdata.properties
- local privates = properties and properties.privates
+ local privates = properties and properties.privates
return privates and privates[name] or false
end
diff --git a/tex/context/base/font-fbk.lua b/tex/context/base/font-fbk.lua
index 89831e7c2..69b45811a 100644
--- a/tex/context/base/font-fbk.lua
+++ b/tex/context/base/font-fbk.lua
@@ -9,40 +9,39 @@ if not modules then modules = { } end modules ['font-fbk'] = {
local cos, tan, rad, format = math.cos, math.tan, math.rad, string.format
local utfbyte, utfchar = utf.byte, utf.char
+--[[ldx--
+<p>This is very experimental code!</p>
+--ldx]]--
+
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 = 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.all", "fonts.combining.all")
local report_combining = logs.reporter("fonts","combining")
-local allocate = utilities.storage.allocate
+local force_combining = false -- just for demo purposes (see mk)
---[[ldx--
-<p>This is very experimental code!</p>
---ldx]]--
+local allocate = utilities.storage.allocate
local fonts = fonts
local handlers = fonts.handlers
local constructors = fonts.constructors
-local vf = handlers.vf
-local commands = vf.combiner.commands
-
-local otffeatures = constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
-local afmfeatures = constructors.newfeatures("afm")
-local registerafmfeature = afmfeatures.register
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
local unicodecharacters = characters.data
local unicodefallbacks = characters.fallbacks
+local vf = handlers.vf
+local commands = vf.combiner.commands
local push = vf.predefined.push
local pop = vf.predefined.pop
+
local force_composed = false
local cache = { } -- we could make these weak
local fraction = 0.15 -- 30 units for lucida
diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua
index 3b87e4c77..b4b073433 100644
--- a/tex/context/base/font-gds.lua
+++ b/tex/context/base/font-gds.lua
@@ -8,44 +8,39 @@ if not modules then modules = { } end modules ['font-gds'] = {
-- depends on ctx
-local type, next = type, next
+local type, next, tonumber = type, next, tonumber
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 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
local otf = fonts.handlers.otf
-local addotffeature = otf.enhancers.addfeature
-
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
-
-local afmfeatures = fonts.constructors.newfeatures("afm")
-local registerafmfeature = afmfeatures.register
+local afm = fonts.handlers.afm
+local tfm = fonts.handlers.tfm
-local tfmfeatures = fonts.constructors.newfeatures("tfm")
-local registertfmfeature = tfmfeatures.register
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+local registertfmfeature = tfm.features.register
-local fontgoodies = { }
+local fontgoodies = fonts.goodies or { }
fonts.goodies = fontgoodies
-local typefaces = allocate()
+local typefaces = fonts.typefaces or allocate()
fonts.typefaces = typefaces
-local data = allocate()
-fontgoodies.data = fontgoodies.data
+local data = fontgoodies.data or allocate()
+fontgoodies.data = data
-local list = { }
+local list = fontgoodies.list or { }
fontgoodies.list = list -- no allocate as we want to see what is there
+local addotffeature = otf.enhancers.addfeature
+
function fontgoodies.report(what,trace,goodies)
if trace_goodies or trace then
local whatever = goodies[what]
@@ -141,7 +136,7 @@ end
-- fonts.features.flattened = flattenedfeatures
-function fontgoodies.prepare_features(goodies,name,set)
+local function prepare_features(goodies,name,set)
if set then
local ff = flattenedfeatures(set)
local fullname = goodies.name .. "::" .. name
@@ -154,6 +149,8 @@ function fontgoodies.prepare_features(goodies,name,set)
end
end
+fontgoodies.prepare_features = prepare_features
+
local function initialize(goodies,tfmdata)
local featuresets = goodies.featuresets
local goodiesname = goodies.name
@@ -162,7 +159,7 @@ local function initialize(goodies,tfmdata)
report_goodies("checking featuresets in '%s'",goodies.name)
end
for name, set in next, featuresets do
- fontgoodies.prepare_features(goodies,name,set)
+ prepare_features(goodies,name,set)
end
end
end
@@ -177,7 +174,7 @@ local function setfeatureset(tfmdata,set,features)
for i=1,#goodies do
-- last one wins
local g = goodies[i]
- what = (g.featuresets and g.featuresets[set]) or what
+ what = g.featuresets and g.featuresets[set] or what
end
if what then
for feature, value in next, what do
@@ -193,12 +190,13 @@ end
-- postprocessors (we could hash processor and share code)
function fontgoodies.registerpostprocessor(tfmdata,f,prepend)
- if not tfmdata.postprocessors then
+ local postprocessors = tfmdata.postprocessors
+ if not postprocessors then
tfmdata.postprocessors = { f }
elseif prepend then
- table.insert(tfmdata.postprocessors,f,1)
+ table.insert(postprocessors,f,1)
else
- table.insert(tfmdata.postprocessors,f)
+ table.insert(postprocessors,f)
end
end
@@ -236,9 +234,9 @@ end
-- colorschemes
-local colorschemes = { }
+local colorschemes = fontgoodies.colorschemes or allocate { }
fontgoodies.colorschemes = colorschemes
-colorschemes.data = { }
+colorschemes.data = colorschemes.data or { }
local function setcolorscheme(tfmdata,scheme)
if type(scheme) == "string" then
@@ -249,7 +247,7 @@ local function setcolorscheme(tfmdata,scheme)
for i=1,#goodies do
-- last one counts
local g = goodies[i]
- what = (g.colorschemes and g.colorschemes[scheme]) or what
+ what = g.colorschemes and g.colorschemes[scheme] or what
end
if type(what) == "table" then
-- this is font bound but we can share them if needed
@@ -605,9 +603,10 @@ end
fontgoodies.register("compositions", initialize)
-local designsizes = { }
+local designsizes = fontgoodies.designsizes or allocate()
fontgoodies.designsizes = designsizes
-local designdata = allocate()
+
+local designdata = designsizes.data or allocate()
designsizes.data = designdata
local function initialize(goodies) -- design sizes are registered global
diff --git a/tex/context/base/font-gds.mkiv b/tex/context/base/font-gds.mkvi
index 2305a0edd..d4760a470 100644
--- a/tex/context/base/font-gds.mkiv
+++ b/tex/context/base/font-gds.mkvi
@@ -37,8 +37,8 @@
\definesystemattribute[colorscheme][public]
-\unexpanded\def\loadfontgoodies[#1]%
- {\ctxcommand{loadfontgoodies("#1")}}
+\unexpanded\def\loadfontgoodies[#filename]%
+ {\ctxcommand{loadfontgoodies("#filename")}}
\unexpanded\def\setfontcolorscheme % will move to the lua end
{\ctxcommand{enablefontcolorschemes()}%
diff --git a/tex/context/base/font-ini.lua b/tex/context/base/font-ini.lua
index 8eeba0ce7..884b22474 100644
--- a/tex/context/base/font-ini.lua
+++ b/tex/context/base/font-ini.lua
@@ -6,33 +6,27 @@ if not modules then modules = { } end modules ['font-ini'] = {
license = "see context related readme files"
}
--- basemethods -> can also be in list
--- presetcontext -> defaults
--- hashfeatures -> ctx version
-
--[[ldx--
<p>Not much is happening here.</p>
--ldx]]--
-local lower = string.lower
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+local allocate = utilities.storage.allocate
local report_defining = logs.reporter("fonts","defining")
-fontloader.totable = fontloader.to_table
-
-fonts = fonts or { } -- already defined in context
+fonts = fonts or { }
local fonts = fonts
--- some of these might move to where they are used first:
-
fonts.hashes = { identifiers = allocate() }
+
+fonts.tables = fonts.tables or { }
+fonts.helpers = fonts.helpers or { }
+fonts.tracers = fonts.tracers or { } -- for the moment till we have move to moduledata
+fonts.specifiers = fonts.specifiers or { } -- in format !
+
fonts.analyzers = { } -- not needed here
fonts.readers = { }
-fonts.tables = { }
fonts.definers = { methods = { } }
-fonts.specifiers = fonts.specifiers or { } -- in format !
fonts.loggers = { register = function() end }
-fonts.helpers = { }
-fonts.tracers = { } -- for the moment till we have move to moduledata
+fontloader.totable = fontloader.to_table
diff --git a/tex/context/base/font-ldr.lua b/tex/context/base/font-ldr.lua
index ca4e3f98a..175b4d0cc 100644
--- a/tex/context/base/font-ldr.lua
+++ b/tex/context/base/font-ldr.lua
@@ -6,8 +6,8 @@ if not modules then modules = { } end modules ['font-ldr'] = {
license = "see context related readme files"
}
--- This module provides a replacement for fontloader.to_table
--- and will be loaded in due time.
+-- This module provides an experimental replacement for fontloader.to_table
+-- but is not used that much.
local fields = fontloader.fields
diff --git a/tex/context/base/font-lib.mkvi b/tex/context/base/font-lib.mkvi
index d9c04f0a2..4ccb6057c 100644
--- a/tex/context/base/font-lib.mkvi
+++ b/tex/context/base/font-lib.mkvi
@@ -27,15 +27,16 @@
\registerctxluafile{font-tfm}{1.001}
\registerctxluafile{font-afm}{1.001}
+\registerctxluafile{font-afk}{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-ota}{1.001} % otf analyzers
\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
@@ -56,7 +57,6 @@
\registerctxluafile{font-ext}{1.001}
\registerctxluafile{font-fbk}{1.001}
-\registerctxluafile{font-chk}{1.001}
\registerctxluafile{font-aux}{1.001}
diff --git a/tex/context/base/font-map.lua b/tex/context/base/font-map.lua
index 7f5305f9a..685f9beea 100644
--- a/tex/context/base/font-map.lua
+++ b/tex/context/base/font-map.lua
@@ -6,18 +6,20 @@ if not modules then modules = { } end modules ['font-map'] = {
license = "see context related readme files"
}
+local tonumber = tonumber
+
local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower
local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match
local utfbyte = utf.byte
-local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end)
+local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end)
local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_unimapping = v end)
local report_fonts = logs.reporter("fonts","loading") -- not otf only
-local fonts = fonts
-local mappings = { }
-fonts.mappings = mappings
+local fonts = fonts
+local mappings = fonts.mappings or { }
+fonts.mappings = mappings
--[[ldx--
<p>Eventually this code will disappear because map files are kind
@@ -40,7 +42,7 @@ end
local hex = R("AF","09")
local hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
local hexsix = (hex^1) / function(s) return tonumber(s,16) end
-local dec = (R("09")^1) / tonumber
+local dec = (R("09")^1) / tonumber
local period = P(".")
local unicode = P("uni") * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true))
local ucode = P("u") * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true))
diff --git a/tex/context/base/font-mat.mkvi b/tex/context/base/font-mat.mkvi
index c8ab45b75..2a4abbff0 100644
--- a/tex/context/base/font-mat.mkvi
+++ b/tex/context/base/font-mat.mkvi
@@ -106,6 +106,7 @@
\def\font_helpers_set_math_family_indeed#mrtag#family% \fontface etc are also used later on
{\let\savedfontbody\fontbody
\let\fontfamily#family%
+ % the order is important as we depend on known id's when completing fonts
\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
diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua
index 9ca357751..c0ee7dec4 100644
--- a/tex/context/base/font-mis.lua
+++ b/tex/context/base/font-mis.lua
@@ -46,7 +46,7 @@ end
local featuregroups = { "gsub", "gpos" }
function fonts.helpers.getfeatures(name,t,script,language) -- maybe per font type
- local t = lower(t or (name and file.extname(name)) or "")
+ local t = lower(t or (name and file.suffix(name)) or "")
if t == "otf" or t == "ttf" or t == "ttc" or t == "dfont" then
local filename = resolvers.findfile(name,t) or ""
if filename ~= "" then
diff --git a/tex/context/base/font-ota.lua b/tex/context/base/font-ota.lua
index edf5996b3..8262f983e 100644
--- a/tex/context/base/font-ota.lua
+++ b/tex/context/base/font-ota.lua
@@ -40,11 +40,6 @@ local fontdata = fonts.hashes.identifiers
local state = attributes.private('state')
local categories = characters and characters.categories or { } -- sorry, only in context
-local tracers = nodes.tracers
-local colortracers = tracers and tracers.colors
-local setnodecolor = colortracers and colortracers.set or function() end
-local resetnodecolor = colortracers and colortracers.reset or function() end
-
local otffeatures = fonts.constructors.newfeatures("otf")
local registerotffeature = otffeatures.register
@@ -53,11 +48,22 @@ local registerotffeature = otffeatures.register
process features right.</p>
--ldx]]--
+analyzers.constants = {
+ init = 1,
+ medi = 2,
+ fina = 3,
+ isol = 4,
+ -- devanagari
+ rphf = 5,
+ half = 6,
+ pref = 7,
+ blwf = 8,
+ pstf = 9,
+}
+
-- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
-- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace
-local state = attributes.private('state')
-
function analyzers.setstate(head,font)
local useunicodemarks = analyzers.useunicodemarks
local tfmdata = fontdata[font]
@@ -117,14 +123,14 @@ end
local function analyzeinitializer(tfmdata,value) -- attr
local script, language = otf.scriptandlanguage(tfmdata) -- attr
local action = initializers[script]
- if action then
- if type(action) == "function" then
+ if not action then
+ -- skip
+ elseif type(action) == "function" then
+ return action(tfmdata,value)
+ else
+ local action = action[language]
+ if action then
return action(tfmdata,value)
- else
- local action = action[language]
- if action then
- return action(tfmdata,value)
- end
end
end
end
@@ -133,14 +139,14 @@ local function analyzeprocessor(head,font,attr)
local tfmdata = fontdata[font]
local script, language = otf.scriptandlanguage(tfmdata,attr)
local action = methods[script]
- if action then
- if type(action) == "function" then
+ if not action then
+ -- skip
+ elseif type(action) == "function" then
+ return action(head,font,attr)
+ else
+ action = action[language]
+ if action then
return action(head,font,attr)
- else
- action = action[language]
- if action then
- return action(head,font,attr)
- end
end
end
return head, false
@@ -239,11 +245,11 @@ local isol_fina_medi_init = {
-- 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,
- [0x0724] = true, [0x0725] = true, [0x0726] = true, [0x0727] = true,
- [0x0729] = true, [0x072B] = true,
+ [0x0712] = true, [0x0713] = true, [0x0714] = true, [0x071A] = true,
+ [0x071B] = true, [0x071C] = true, [0x071D] = true, [0x071F] = true,
+ [0x0720] = true, [0x0721] = true, [0x0722] = true, [0x0723] = true,
+ [0x0724] = true, [0x0725] = true, [0x0726] = true, [0x0727] = true,
+ [0x0729] = true, [0x072B] = true,
-- also
@@ -252,7 +258,6 @@ local isol_fina_medi_init = {
local arab_warned = { }
-
-- todo: gref
local function warning(current,what)
@@ -263,37 +268,24 @@ local function warning(current,what)
end
end
-function methods.nocolor(head,font,attr)
- for n in traverse_id(glyph_code,head) do
- if not font or n.font == font then
- resetnodecolor(n)
- end
- end
- return head, true
-end
-
local function finish(first,last)
if last then
if first == last then
local fc = first.char
if isol_fina_medi_init[fc] or isol_fina[fc] then
set_attribute(first,state,4) -- isol
- if trace_analyzing then setnodecolor(first,"font:isol") end
else
warning(first,"isol")
set_attribute(first,state,0) -- error
- if trace_analyzing then resetnodecolor(first) end
end
else
local lc = last.char
if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ?
-- if laststate == 1 or laststate == 2 or laststate == 4 then
set_attribute(last,state,3) -- fina
- if trace_analyzing then setnodecolor(last,"font:fina") end
else
warning(last,"fina")
set_attribute(last,state,0) -- error
- if trace_analyzing then resetnodecolor(last) end
end
end
first, last = nil, nil
@@ -302,11 +294,9 @@ local function finish(first,last)
local fc = first.char
if isol_fina_medi_init[fc] or isol_fina[fc] then
set_attribute(first,state,4) -- isol
- if trace_analyzing then setnodecolor(first,"font:isol") end
else
warning(first,"isol")
set_attribute(first,state,0) -- error
- if trace_analyzing then resetnodecolor(first) end
end
first = nil
end
@@ -324,20 +314,16 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr
local char = current.char
if marks[char] or (useunicodemarks and categories[char] == "mn") then
set_attribute(current,state,5) -- mark
- if trace_analyzing then setnodecolor(current,"font:mark") end
elseif isol[char] then -- can be zwj or zwnj too
first, last = finish(first,last)
set_attribute(current,state,4) -- isol
- if trace_analyzing then setnodecolor(current,"font:isol") end
first, last = nil, nil
elseif not first then
if isol_fina_medi_init[char] then
set_attribute(current,state,1) -- init
- if trace_analyzing then setnodecolor(current,"font:init") end
first, last = first or current, current
elseif isol_fina[char] then
set_attribute(current,state,4) -- isol
- if trace_analyzing then setnodecolor(current,"font:isol") end
first, last = nil, nil
else -- no arab
first, last = finish(first,last)
@@ -345,18 +331,15 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr
elseif isol_fina_medi_init[char] then
first, last = first or current, current
set_attribute(current,state,2) -- medi
- if trace_analyzing then setnodecolor(current,"font:medi") end
elseif isol_fina[char] then
if not has_attribute(last,state,1) then
-- tricky, we need to check what last may be !
set_attribute(last,state,2) -- medi
- if trace_analyzing then setnodecolor(last,"font:medi") end
end
set_attribute(current,state,3) -- fina
- if trace_analyzing then setnodecolor(current,"font:fina") end
first, last = nil, nil
elseif char >= 0x0600 and char <= 0x06FF then
- if trace_analyzing then setnodecolor(current,"font:rest") end
+ set_attribute(current,state,6) -- rest
first, last = finish(first,last)
else --no
first, last = finish(first,last)
diff --git a/tex/context/base/font-otb.lua b/tex/context/base/font-otb.lua
index 44639a80a..04e289ba9 100644
--- a/tex/context/base/font-otb.lua
+++ b/tex/context/base/font-otb.lua
@@ -11,26 +11,27 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring
local lpegmatch = lpeg.match
local utfchar = utf.char
-local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = 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_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
-local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
+local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = 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_ligatures_detail = false trackers.register("otf.ligatures.detail", function(v) trace_ligatures_detail = v end)
+local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
+local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
-local report_prepare = logs.reporter("fonts","otf prepare")
+local report_prepare = logs.reporter("fonts","otf prepare")
-local fonts = fonts
-local otf = fonts.handlers.otf
+local fonts = fonts
+local otf = fonts.handlers.otf
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
+local otffeatures = otf.features
+local registerotffeature = otffeatures.register
-otf.defaultbasealternate = "none" -- first last
+otf.defaultbasealternate = "none" -- first last
-local wildcard = "*"
-local default = "dflt"
+local wildcard = "*"
+local default = "dflt"
local function gref(descriptions,n)
if type(n) == "number" then
@@ -165,7 +166,7 @@ local function finalize_ligatures(tfmdata,ligatures)
if ligature then
local unicode, lookupdata = ligature[1], ligature[2]
if trace then
- print("BUILDING",concat(lookupdata," "),unicode)
+ trace_ligatures_detail("building %q into %q",concat(lookupdata," "),unicode)
end
local size = #lookupdata
local firstcode = lookupdata[1] -- [2]
@@ -178,7 +179,7 @@ local function finalize_ligatures(tfmdata,ligatures)
if not firstdata then
firstcode = private
if trace then
- print(" DEFINING",firstname,firstcode)
+ trace_ligatures_detail("defining %q as %q",firstname,firstcode)
end
unicodes[firstname] = firstcode
firstdata = { intermediate = true, ligatures = { } }
@@ -202,7 +203,7 @@ local function finalize_ligatures(tfmdata,ligatures)
end
end
if trace then
- print("CODES",firstname,firstcode,secondname,secondcode,target)
+ trace_ligatures_detail("codes (%s,%s) + (%s,%s) -> %s",firstname,firstcode,secondname,secondcode,target)
end
local firstligs = firstdata.ligatures
if firstligs then
diff --git a/tex/context/base/font-otc.lua b/tex/context/base/font-otc.lua
index ae463e750..777267254 100644
--- a/tex/context/base/font-otc.lua
+++ b/tex/context/base/font-otc.lua
@@ -17,8 +17,7 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
+local registerotffeature = otf.features.register
local setmetatableindex = table.setmetatableindex
-- In the userdata interface we can not longer tweak the loaded font as
diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua
index ebd487959..0bc8225de 100644
--- a/tex/context/base/font-otd.lua
+++ b/tex/context/base/font-otd.lua
@@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['font-otd'] = {
license = "see context related readme files"
}
+local type = type
local match = string.match
local sequenced = table.sequenced
@@ -115,16 +116,11 @@ end
-- we reimplement the dataset resolver
-local special_attributes = {
- init = 1,
- medi = 2,
- fina = 3,
- isol = 4
-}
+local constants = fonts.analyzers.constants
-local resolved = { } -- we only resolve a font,script,language,attribute pair once
-local wildcard = "*"
-local default = "dflt"
+local resolved = { } -- we only resolve a font,script,language,attribute pair once
+local wildcard = "*"
+local default = "dflt"
local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic)
local features = sequence.features
@@ -151,7 +147,7 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr
what = wildcard
end
if valid then
- local attribute = special_attributes[kind] or false
+ local attribute = constants[kind] or false
if a_e and dynamic < 0 then
valid = false
end
@@ -180,7 +176,7 @@ end
-- return v
-- end)
-function otf.dataset(tfmdata,sequences,font,attr) -- attr only when explicit (as in special parbuilder)
+function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder)
local script, language, s_enabled, a_enabled, dynamic
@@ -220,12 +216,17 @@ function otf.dataset(tfmdata,sequences,font,attr) -- attr only when explicit (as
end
local ra = rl[attr]
if ra == nil then -- attr can be false
- ra = { }
+ ra = {
+ -- indexed but we can also add specific data by key in:
+ }
rl[attr] = ra
+ local sequences = tfmdata.resources.sequences
setmetatableindex(ra, function(t,k)
- local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic)
- t[k] = v or false
- return v
+ if type(k) == "number" then
+ local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic)
+ t[k] = v or false
+ return v
+ end
end)
end
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index e1339aec9..9f0fb6657 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -1114,7 +1114,7 @@ actions["prepare lookups"] = function(data,filename,raw)
end
-- The reverse handler does a bit redundant splitting but it's seldom
--- seen so we don' tbother too much. We could store the replacement
+-- seen so we don't bother too much. We could store the replacement
-- in the current list (value instead of true) but it makes other code
-- uglier. Maybe some day.
@@ -1132,6 +1132,22 @@ local function t_uncover(splitter,cache,covers)
return result
end
+local function s_uncover(splitter,cache,cover)
+ if cover == "" then
+ return nil
+ else
+ local uncovered = cache[cover]
+ if not uncovered then
+ uncovered = lpegmatch(splitter,cover)
+-- for i=1,#uncovered do
+-- uncovered[i] = { [uncovered[i]] = true }
+-- end
+ cache[cover] = uncovered
+ end
+ return { uncovered }
+ end
+end
+
local function t_hashed(t,cache)
if t then
local ht = { }
@@ -1153,22 +1169,6 @@ local function t_hashed(t,cache)
end
end
-local function s_uncover(splitter,cache,cover)
- if cover == "" then
- return nil
- else
- local uncovered = cache[cover]
- if not uncovered then
- uncovered = lpegmatch(splitter,cover)
- for i=1,#uncovered do
- uncovered[i] = { [uncovered[i]] = true }
- end
- cache[cover] = uncovered
- end
- return uncovered
- end
-end
-
local s_hashed = t_hashed
local function r_uncover(splitter,cache,cover,replacements)
@@ -1193,11 +1193,15 @@ local function r_uncover(splitter,cache,cover,replacements)
end
end
-actions["reorganize lookups"] = function(data,filename,raw)
+actions["reorganize lookups"] = function(data,filename,raw) -- we could check for "" and n == 0
-- we prefer the before lookups in a normal order
if data.lookups then
local splitter = data.helpers.tounicodetable
- local cache, h_cache = { }, { }
+ local t_u_cache = { }
+ local s_u_cache = t_u_cache -- string keys
+ local t_h_cache = { }
+ local s_h_cache = t_h_cache -- table keys (so we could use one cache)
+ local r_u_cache = { } -- maybe shared
for _, lookup in next, data.lookups do
local rules = lookup.rules
if rules then
@@ -1205,15 +1209,15 @@ actions["reorganize lookups"] = function(data,filename,raw)
if format == "class" then
local before_class = lookup.before_class
if before_class then
- before_class = t_uncover(splitter,cache,reversed(before_class))
+ before_class = t_uncover(splitter,t_u_cache,reversed(before_class))
end
local current_class = lookup.current_class
if current_class then
- current_class = t_uncover(splitter,cache,current_class)
+ current_class = t_uncover(splitter,t_u_cache,current_class)
end
local after_class = lookup.after_class
if after_class then
- after_class = t_uncover(splitter,cache,after_class)
+ after_class = t_uncover(splitter,t_u_cache,after_class)
end
for i=1,#rules do
local rule = rules[i]
@@ -1223,7 +1227,7 @@ actions["reorganize lookups"] = function(data,filename,raw)
for i=1,#before do
before[i] = before_class[before[i]] or { }
end
- rule.before = t_hashed(before,h_cache)
+ rule.before = t_hashed(before,t_h_cache)
end
local current = class.current
local lookups = rule.lookups
@@ -1234,14 +1238,14 @@ actions["reorganize lookups"] = function(data,filename,raw)
lookups[i] = false -- e.g. we can have two lookups and one replacement
end
end
- rule.current = t_hashed(current,h_cache)
+ rule.current = t_hashed(current,t_h_cache)
end
local after = class.after
if after then
for i=1,#after do
after[i] = after_class[after[i]] or { }
end
- rule.after = t_hashed(after,h_cache)
+ rule.after = t_hashed(after,t_h_cache)
end
rule.class = nil
end
@@ -1256,18 +1260,18 @@ actions["reorganize lookups"] = function(data,filename,raw)
if coverage then
local before = coverage.before
if before then
- before = t_uncover(splitter,cache,reversed(before))
- rule.before = t_hashed(before,h_cache)
+ before = t_uncover(splitter,t_u_cache,reversed(before))
+ rule.before = t_hashed(before,t_h_cache)
end
local current = coverage.current
if current then
- current = t_uncover(splitter,cache,current)
- rule.current = t_hashed(current,h_cache)
+ current = t_uncover(splitter,t_u_cache,current)
+ rule.current = t_hashed(current,t_h_cache)
end
local after = coverage.after
if after then
- after = t_uncover(splitter,cache,after)
- rule.after = t_hashed(after,h_cache)
+ after = t_uncover(splitter,t_u_cache,after)
+ rule.after = t_hashed(after,t_h_cache)
end
rule.coverage = nil
end
@@ -1279,22 +1283,22 @@ actions["reorganize lookups"] = function(data,filename,raw)
if reversecoverage then
local before = reversecoverage.before
if before then
- before = t_uncover(splitter,cache,reversed(before))
- rule.before = t_hashed(before,h_cache)
+ before = t_uncover(splitter,t_u_cache,reversed(before))
+ rule.before = t_hashed(before,t_h_cache)
end
local current = reversecoverage.current
if current then
- current = t_uncover(splitter,cache,current)
- rule.current = t_hashed(current,h_cache)
+ current = t_uncover(splitter,t_u_cache,current)
+ rule.current = t_hashed(current,t_h_cache)
end
local after = reversecoverage.after
if after then
- after = t_uncover(splitter,cache,after)
- rule.after = t_hashed(after,h_cache)
+ after = t_uncover(splitter,t_u_cache,after)
+ rule.after = t_hashed(after,t_h_cache)
end
local replacements = reversecoverage.replacements
if replacements then
- rule.replacements = r_uncover(splitter,cache,current,replacements)
+ rule.replacements = r_uncover(splitter,r_u_cache,current,replacements)
end
rule.reversecoverage = nil
end
@@ -1305,19 +1309,19 @@ actions["reorganize lookups"] = function(data,filename,raw)
local glyphs = rule.glyphs
if glyphs then
local fore = glyphs.fore
- if fore then
- fore = s_uncover(splitter,cache,fore)
- rule.before = s_hashed(fore,h_cache)
+ if fore and fore ~= "" then
+ fore = s_uncover(splitter,s_u_cache,fore)
+ rule.before = s_hashed(fore,s_h_cache)
end
local back = glyphs.back
if back then
- back = s_uncover(splitter,cache,back)
- rule.after = s_hashed(back,h_cache)
+ back = s_uncover(splitter,s_u_cache,back)
+ rule.after = s_hashed(back,s_h_cache)
end
local names = glyphs.names
if names then
- names = s_uncover(splitter,cache,names)
- rule.current = s_hashed(names,h_cache)
+ names = s_uncover(splitter,s_u_cache,names)
+ rule.current = s_hashed(names,s_h_cache)
end
rule.glyphs = nil
end
@@ -1972,7 +1976,7 @@ local function read_from_otf(specification)
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)
+ fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
end
return tfmdata
end
diff --git a/tex/context/base/font-oti.lua b/tex/context/base/font-oti.lua
index d6853db31..06c2a42fa 100644
--- a/tex/context/base/font-oti.lua
+++ b/tex/context/base/font-oti.lua
@@ -8,15 +8,16 @@ if not modules then modules = { } end modules ['font-oti'] = {
local lower = string.lower
-local allocate = utilities.storage.allocate
-
local fonts = fonts
-local otf = { }
-fonts.handlers.otf = otf
+local constructors = fonts.constructors
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otf = constructors.newhandler("otf")
+local otffeatures = constructors.newfeatures("otf")
+local otftables = otf.tables
local registerotffeature = otffeatures.register
+local allocate = utilities.storage.allocate
+
registerotffeature {
name = "features",
description = "initialization of feature handler",
@@ -25,8 +26,6 @@ registerotffeature {
-- these are later hooked into node and base initializaters
-local otftables = otf.tables -- not always defined
-
local function setmode(tfmdata,value)
if value then
tfmdata.properties.mode = lower(value)
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index d97ef7363..2c670825a 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -116,6 +116,8 @@ results in different tables.</p>
-- we now use only one hash. If needed we can have multiple again but in that
-- case I will probably prefix (i.e. rename) the lookups in the cached font file.
+-- Todo: make plugin feature that operates on char/glyphnode arrays
+
local concat, insert, remove = table.concat, table.insert, table.remove
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring = type, next, tonumber, tostring
@@ -151,6 +153,7 @@ local report_subchain = logs.reporter("fonts","otf subchain")
local report_chain = logs.reporter("fonts","otf chain")
local report_process = logs.reporter("fonts","otf process")
local report_prepare = logs.reporter("fonts","otf prepare")
+local report_warning = logs.reporter("fonts","otf warning")
registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
@@ -310,105 +313,229 @@ local function pref(kind,lookupname)
return format("feature %s, lookup %s",kind,lookupname)
end
--- we can assume that languages that use marks are not hyphenated
--- we can also assume that at most one discretionary is present
-
-local function markstoligature(kind,lookupname,start,stop,char)
- local n = copy_node(start)
- local keep = start
- local current
- current, start = insert_node_after(start,start,n)
- local snext = stop.next
- current.next = snext
- if snext then
- snext.prev = current
+-- We can assume that languages that use marks are not hyphenated. We can also assume
+-- that at most one discretionary is present.
+
+-- 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. Also, later on copying and freeing becomes easier.
+-- However, for arabic we need to keep them around for the sake of mark placement
+-- and indices.
+
+local function copy_glyph(g) -- next and prev are untouched !
+ local components = g.components
+ if components then
+ g.components = nil
+ local n = copy_node(g)
+ g.components = components
+ return n
+ else
+ return copy_node(g)
end
- start.prev, stop.next = nil, nil
- current.char, current.subtype, current.components = char, ligature_code, start
- return keep
end
-local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
- if start == stop then
- start.char = char
+-- start is a mark and we need to keep that one
+
+-- local function markstoligature(kind,lookupname,start,stop,char)
+-- -- [start]..[stop]
+-- local keep = start
+-- local prev = start.prev
+-- local next = stop.next
+-- local base = copy_glyph(start)
+-- local current, start = insert_node_after(start,start,base)
+-- -- [current][start]..[stop]
+-- current.next = next
+-- if next then
+-- next.prev = current
+-- end
+-- start.prev = nil
+-- stop.next = nil
+-- current.char = char
+-- current.subtype = ligature_code
+-- current.components = start
+-- return keep
+-- end
+
+local function markstoligature(kind,lookupname,start,stop,char)
+ if start == stop and start.char == char then
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 = start.font
- lignode.char = char
- lignode.subtype = ligature_code
- local next = stop.next
+ else
local prev = start.prev
- stop.next = nil
+ local next = stop.next
start.prev = nil
- lignode.components = start
- -- print("lignode",nodes.tosequence(lignode))
- -- print("components",nodes.tosequence(lignode.components))
- prev.next = lignode
+ stop.next = nil
+ local base = copy_glyph(start)
+ base.char = char
+ base.subtype = ligature_code
+ base.components = start
+ if prev then
+ prev.next = base
+ end
if next then
- next.prev = lignode
+ next.prev = base
end
- lignode.next = next
- lignode.prev = prev
- -- print("start->end",nodes.tosequence(start))
- return lignode
+ base.next = next
+ base.prev = prev
+ return base
+ end
+end
+
+-- The next code is somewhat complicated by the fact that some fonts can have ligatures made
+-- from ligatures that themselves have marks. This was identified by Kai in for instance
+-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes
+-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next
+-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
+-- third component.
+
+local function getcomponentindex(start)
+ if start.id ~= glyph_code then
+ return 0
+ elseif start.subtype == ligature_code then
+ local i = 0
+ local components = start.components
+ while components do
+ i = i + getcomponentindex(components)
+ components = components.next
+ end
+ return i
+ elseif not marks[start.char] then
+ return 1
else
- -- start is the ligature
+ return 0
+ end
+end
+
+-- local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
+-- if start == stop and start.char == char then
+-- start.char = char
+-- return start
+-- elseif discfound then
+-- local prev = start.prev
+-- local next = stop.next
+-- start.prev = nil
+-- stop.next = nil
+-- local base = copy_glyph(start)
+-- base.char = char
+-- base.subtype = ligature_code
+-- base.components = start -- start can have components
+-- if prev then
+-- prev.next = base
+-- end
+-- if next then
+-- next.prev = base
+-- end
+-- base.next = next
+-- base.prev = prev
+-- return base
+-- else
+-- -- start is the ligature
+-- local deletemarks = markflag ~= "mark"
+-- local prev = start.prev
+-- local next = stop.next
+-- local base = copy_glyph(start)
+-- local current, start = insert_node_after(start,start,base)
+-- -- [start->current][copyofstart->start]...[stop]
+-- current.next = next
+-- if next then
+-- next.prev = current
+-- end
+-- start.prev = nil
+-- stop.next = nil
+-- current.char = char
+-- current.subtype = ligature_code
+-- current.components = start
+-- local head = current
+-- -- this is messy ... we should get rid of the components eventually
+-- local baseindex = 0
+-- local componentindex = 0
+-- while start do
+-- local char = start.char
+-- if not marks[char] then
+-- baseindex = baseindex + componentindex
+-- componentindex = getcomponentindex(start)
+-- elseif not deletemarks then -- quite fishy
+-- set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex))
+-- if trace_marks then
+-- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp))
+-- end
+-- head, current = insert_node_after(head,current,copy_glyph(start)) -- unlikely that mark has components
+-- end
+-- start = start.next
+-- end
+-- start = current.next
+-- while start and start.id == glyph_code do -- hm, is id test needed ?
+-- local char = start.char
+-- if marks[char] then
+-- set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex))
+-- if trace_marks then
+-- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp))
+-- end
+-- else
+-- break
+-- end
+-- start = start.next
+-- end
+-- return head
+-- end
+-- end
+
+local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
+ if start == stop and start.char == char then
+ start.char = char
+ return start
+ end
+ local prev = start.prev
+ local next = stop.next
+ start.prev = nil
+ stop.next = nil
+ local base = copy_glyph(start)
+ base.char = char
+ base.subtype = ligature_code
+ base.components = start -- start can have components
+ if prev then
+ prev.next = base
+ end
+ if next then
+ next.prev = base
+ end
+ base.next = next
+ base.prev = prev
+ if not discfound then
local deletemarks = markflag ~= "mark"
- local n = copy_node(start)
- local current
- current, start = insert_node_after(start,start,n)
- local snext = stop.next
- current.next = snext
- if snext then
- snext.prev = current
- end
- start.prev = nil
- stop.next = nil
- current.char = char
- current.subtype = ligature_code
- current.components = start
- local head = current
- -- this is messy ... we should get rid of the components eventually
- local i = 0 -- is index of base
+ local components = start
+ local baseindex = 0
+ local componentindex = 0
+ local head = base
+ local current = base
while start do
- if not marks[start.char] then
- i = i + 1
+ local char = start.char
+ if not marks[char] then
+ baseindex = baseindex + componentindex
+ componentindex = getcomponentindex(start)
elseif not deletemarks then -- quite fishy
- set_attribute(start,ligacomp,i)
+ set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex))
if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp))
end
- head, current = insert_node_after(head,current,copy_node(start))
+ head, current = insert_node_after(head,current,copy_node(start)) -- unlikely that mark has components
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)
+ local start = components
+ while start and start.id == glyph_code do -- hm, is id test needed ?
+ local char = start.char
+ if marks[char] then
+ set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex))
if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp))
end
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 base
end
function handlers.gsub_single(start,kind,lookupname,replacement)
@@ -463,7 +590,7 @@ local function multiple_glyphs(start,multiple) -- marks ?
if nofmultiples > 1 then
local sn = start.next
for k=2,nofmultiples do -- todo: use insert_node
- local n = copy_node(start)
+ local n = copy_node(start) -- ignore components
n.char = multiple[k]
n.next = sn
n.prev = start
@@ -488,12 +615,12 @@ function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence)
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)
+ logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.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))
+ logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(start.char))
end
end
return start, true
@@ -987,6 +1114,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start
repeat -- start x x m x x stop => start m
local next = start.next
if not marks[next.char] then
+local components = next.components
+if components then -- probably not needed
+ flush_node_list(components)
+end
delete_node(start,next)
end
n = n + 1
@@ -994,6 +1125,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start
else -- start x x x stop => start
repeat
local next = start.next
+local components = next.components
+if components then -- probably not needed
+ flush_node_list(components)
+end
delete_node(start,next)
n = n + 1
until next == stop
@@ -1722,7 +1857,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
break
end
prev = prev.prev
- elseif seq[n][32] then -- somehat special, as zapfino can have many preceding spaces
+ elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
n = n -1
else
match = false
@@ -1962,12 +2097,7 @@ end)
-- fonts.hashes.lookups = lookuphashes
-local special_attributes = {
- init = 1,
- medi = 2,
- fina = 3,
- isol = 4
-}
+local constants = fonts.analyzers.constants
local function initialize(sequence,script,language,enabled)
local features = sequence.features
@@ -1977,7 +2107,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, sequence }
+ return { valid, constants[kind] or false, sequence.chain or 0, kind, sequence }
end
end
end
@@ -1985,7 +2115,7 @@ local function initialize(sequence,script,language,enabled)
return false
end
-function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in context
+function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
local shared = tfmdata.shared
local properties = tfmdata.properties
local language = properties.language or "dflt"
@@ -2003,12 +2133,17 @@ function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in c
end
local rl = rs[language]
if not rl then
- rl = { }
+ rl = {
+ -- indexed but we can also add specific data by key
+ }
rs[language] = rl
+ local sequences = tfmdata.resources.sequences
setmetatableindex(rl, function(t,k)
- local v = enabled and initialize(sequences[k],script,language,enabled)
- t[k] = v
- return v
+ if type(k) == "number" then
+ local v = enabled and initialize(sequences[k],script,language,enabled)
+ t[k] = v
+ return v
+ end
end)
end
return rl
@@ -2030,6 +2165,8 @@ end
-- start = start.next
-- end
+-- there will be a new direction parser (pre-parsed etc)
+
local function featuresprocessor(head,font,attr)
local lookuphash = lookuphashes[font] -- we can also check sequences here
@@ -2057,7 +2194,7 @@ local function featuresprocessor(head,font,attr)
local sequences = resources.sequences
local done = false
- local datasets = otf.dataset(tfmdata,sequences,font,attr)
+ local datasets = otf.dataset(tfmdata,font,attr)
local dirstack = { } -- could move outside function
@@ -2066,6 +2203,9 @@ local function featuresprocessor(head,font,attr)
-- 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.
+ -- Keeping track of the headnode is needed for devanagari (I generalized it a bit
+ -- so that multiple cases are also covered.
+
for s=1,#sequences do
local dataset = datasets[s]
if dataset then
@@ -2101,8 +2241,12 @@ local function featuresprocessor(head,font,attr)
if lookupcache then
local lookupmatch = lookupcache[start.char]
if lookupmatch then
+ local headnode = start == head
start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
if success then
+ if headnode then
+ head = start
+ end
break
end
end
@@ -2146,10 +2290,14 @@ local function featuresprocessor(head,font,attr)
local lookupmatch = lookupcache[start.char]
if lookupmatch then
-- sequence kan weg
+ local headnode = start == head
local ok
start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
success = true
+ if headnode then
+ head = start
+ end
end
end
if start then start = start.next end
@@ -2219,10 +2367,14 @@ local function featuresprocessor(head,font,attr)
local lookupmatch = lookupcache[start.char]
if lookupmatch then
-- we could move all code inline but that makes things even more unreadable
+ local headnode = start == head
local ok
start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
success = true
+ if headnode then
+ head = start
+ end
break
end
end
@@ -2548,3 +2700,7 @@ registerotffeature {
node = featuresprocessor,
}
}
+
+-- this will change but is needed for an experiment:
+
+otf.handlers = handlers
diff --git a/tex/context/base/font-otp.lua b/tex/context/base/font-otp.lua
index f019ade7f..6c9827de8 100644
--- a/tex/context/base/font-otp.lua
+++ b/tex/context/base/font-otp.lua
@@ -17,14 +17,18 @@ local report_otf = logs.reporter("fonts","otf loading")
-- also used in other scripts so we need to check some tables:
fonts = fonts or { }
-fonts.handlers = fonts.handlers or { }
-local handlers = fonts.handlers
-handlers.otf = handlers.otf or { }
-local otf = handlers.otf
-otf.enhancers = otf.enhancers or { }
-local enhancers = otf.enhancers
-otf.glists = otf.glists or { "gsub", "gpos" }
-local glists = otf.glists
+
+local handlers = fonts.handlers or { }
+fonts.handlers = handlers
+
+local otf = handlers.otf or { }
+handlers.otf = otf
+
+local enhancers = otf.enhancers or { }
+otf.enhancers = enhancers
+
+local glists = otf.glists or { "gsub", "gpos" }
+otf.glists = glists
local criterium = 1
local threshold = 0
@@ -43,12 +47,30 @@ local function tabstr(t)
s[n] = k .. "=false"
end
end
- sort(s)
- return concat(s,",")
+ if n == 1 then
+ return s[1]
+ else
+ sort(s)
+ return concat(s,",")
+ end
end
+
+-- -- saves only a few tens of bytes
+--
+-- local function stripdata(data)
+-- for k, v in next, data do
+-- if not v or v == "" then
+-- data[k] = nil
+-- elseif type(v) == "table" then
+-- stripdata(v) -- keep empty tables
+-- end
+-- end
+-- end
+
local function packdata(data)
if data then
+ -- stripdata(data)
local h, t, c = { }, { }, { }
local hh, tt, cc = { }, { }, { }
local nt, ntt = 0, 0
@@ -202,21 +224,10 @@ local function packdata(data)
if rules then
for i=1,#rules do -- was next loop
local rule = rules[i]
---~ local r = rule.before if r then for i=1,#r do r[i] = pack(r[i],true) end end
---~ local r = rule.after if r then for i=1,#r do r[i] = pack(r[i],true) end end
---~ local r = rule.current if r then for i=1,#r do r[i] = pack(r[i],true) end end
---~ local r = rule.replacements if r then rule.replacements = pack(r, true) end
---~ local r = rule.fore if r then rule.fore = pack(r, true) end
---~ local r = rule.back if r then rule.back = pack(r, true) end
---~ local r = rule.names if r then rule.names = pack(r, true) end
---~ local r = rule.lookups if r then rule.lookups = pack(r) end
local r = rule.before if r then for i=1,#r do r[i] = pack(r[i]) end end
local r = rule.after if r then for i=1,#r do r[i] = pack(r[i]) end end
local r = rule.current if r then for i=1,#r do r[i] = pack(r[i]) end end
local r = rule.replacements if r then rule.replacements = pack(r) end
- -- local r = rule.fore if r then rule.fore = pack(r) end
- -- local r = rule.back if r then rule.back = pack(r) end
- -- local r = rule.names if r then rule.names = pack(r) end
local r = rule.lookups if r then rule.lookups = pack(r) end
end
end
diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua
index 6c671d76f..c0a6c4d27 100644
--- a/tex/context/base/font-ott.lua
+++ b/tex/context/base/font-ott.lua
@@ -1,9 +1,10 @@
-if not modules then modules = { } end modules ['font-otf'] = {
+if not modules then modules = { } end modules ['font-ott'] = {
version = 1.001,
comment = "companion to font-otf.lua (tables)",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+ license = "see context related readme files",
+ -- dataonly = true,
}
local type, next, tonumber, tostring, rawget, rawset = type, next, tonumber, tostring, rawget, rawset
@@ -16,11 +17,14 @@ local allocate = utilities.storage.allocate
local fonts = fonts
local otf = fonts.handlers.otf
-local tables = { }
+local otffeatures = otf.features
+local registerotffeature = otffeatures.register
+
+local tables = otf.tables or { }
otf.tables = tables
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
+local statistics = otf.statistics or { }
+otf.statistics = statistics
local scripts = allocate {
['arab'] = 'arabic',
@@ -577,26 +581,26 @@ local features = allocate {
['size'] = 'optical size',
['smcp'] = 'small capitals',
['smpl'] = 'simplified forms',
- ['ss01'] = 'stylistic set 1',
- ['ss02'] = 'stylistic set 2',
- ['ss03'] = 'stylistic set 3',
- ['ss04'] = 'stylistic set 4',
- ['ss05'] = 'stylistic set 5',
- ['ss06'] = 'stylistic set 6',
- ['ss07'] = 'stylistic set 7',
- ['ss08'] = 'stylistic set 8',
- ['ss09'] = 'stylistic set 9',
- ['ss10'] = 'stylistic set 10',
- ['ss11'] = 'stylistic set 11',
- ['ss12'] = 'stylistic set 12',
- ['ss13'] = 'stylistic set 13',
- ['ss14'] = 'stylistic set 14',
- ['ss15'] = 'stylistic set 15',
- ['ss16'] = 'stylistic set 16',
- ['ss17'] = 'stylistic set 17',
- ['ss18'] = 'stylistic set 18',
- ['ss19'] = 'stylistic set 19',
- ['ss20'] = 'stylistic set 20',
+ -- ['ss01'] = 'stylistic set 1',
+ -- ['ss02'] = 'stylistic set 2',
+ -- ['ss03'] = 'stylistic set 3',
+ -- ['ss04'] = 'stylistic set 4',
+ -- ['ss05'] = 'stylistic set 5',
+ -- ['ss06'] = 'stylistic set 6',
+ -- ['ss07'] = 'stylistic set 7',
+ -- ['ss08'] = 'stylistic set 8',
+ -- ['ss09'] = 'stylistic set 9',
+ -- ['ss10'] = 'stylistic set 10',
+ -- ['ss11'] = 'stylistic set 11',
+ -- ['ss12'] = 'stylistic set 12',
+ -- ['ss13'] = 'stylistic set 13',
+ -- ['ss14'] = 'stylistic set 14',
+ -- ['ss15'] = 'stylistic set 15',
+ -- ['ss16'] = 'stylistic set 16',
+ -- ['ss17'] = 'stylistic set 17',
+ -- ['ss18'] = 'stylistic set 18',
+ -- ['ss19'] = 'stylistic set 19',
+ -- ['ss20'] = 'stylistic set 20',
['ssty'] = 'script style', -- math
['subs'] = 'subscript',
['sups'] = 'superscript',
@@ -622,7 +626,11 @@ local features = allocate {
['trep'] = 'traditional tex replacements',
['tlig'] = 'traditional tex ligatures',
- ['ss'] = 'stylistic set %s',
+ ['ss..'] = 'stylistic set ..',
+ ['cv..'] = 'character variant ..',
+ ['js..'] = 'justification ..',
+
+ ["dv.."] = "devanagari ..",
}
local baselines = allocate {
@@ -635,16 +643,16 @@ 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
+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")
+
-- hm, we overload the metatables
if otffeatures.features then
@@ -684,6 +692,10 @@ setmetatableindex(verboselanguages, resolve)
setmetatableindex(verbosefeatures, resolve)
setmetatableindex(verbosebaselines, resolve)
+-- We could optimize the next lookups by using an extra metatable and storing
+-- already found values but in practice there are not that many lookups so
+-- it's never a bottleneck.
+
setmetatableindex(scripts, function(t,k)
if k then
k = lower(k)
@@ -750,7 +762,12 @@ local function resolve(t,k)
if tag and dd then
local v = rawget(t,tag)
if v then
- return format(v,tonumber(dd))
+ return v -- return format(v,tonumber(dd)) -- old way
+ else
+ local v = rawget(t,tag.."..") -- nicer in overview
+ if v then
+ return (gsub(v,"%.%.",tonumber(dd))) -- new way
+ end
end
end
end
@@ -760,10 +777,10 @@ end
setmetatableindex(features, resolve)
local function assign(t,k,v)
- if k then
+ if k and v then
v = lower(v)
- rawset(t,k,v)
- rawset(features,gsub(v,"[^a-z0-9]",""),k)
+ rawset(t,k,v) -- rawset ?
+ -- rawset(features,gsub(v,"[^a-z0-9]",""),k) -- why ? old code
end
end
@@ -775,31 +792,85 @@ local checkers = {
end
}
-function otf.features.normalize(features) -- no longer 'lang'
+-- Keep this:
+--
+-- function otf.features.normalize(features)
+-- if features then
+-- local h = { }
+-- for k, v in next, features do
+-- k = lower(k)
+-- if k == "language" then
+-- v = gsub(lower(v),"[^a-z0-9]","")
+-- 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]","")
+-- 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)
+-- if type(b) == "nil" then
+-- v = tonumber(v) or lower(v)
+-- else
+-- v = b
+-- end
+-- end
+-- if not rawget(features,k) then
+-- k = rawget(verbosefeatures,k) or k
+-- end
+-- local c = checkers[k]
+-- h[k] = c and c(v) or v
+-- end
+-- end
+-- return h
+-- end
+-- end
+
+-- inspect(fonts.handlers.otf.statistics.usedfeatures)
+
+local usedfeatures = statistics.usedfeatures or { }
+statistics.usedfeatures = usedfeatures
+
+table.setmetatableindex(usedfeatures, function(t,k) if k then local v = { } t[k] = v return v end end) -- table.autotable
+
+storage.register("fonts/otf/usedfeatures", usedfeatures, "fonts.handlers.otf.statistics.usedfeatures" )
+
+function otf.features.normalize(features)
if features then
local h = { }
- for k, v in next, features do
- k = lower(k)
+ for key, value in next, features do
+ local k = lower(key)
if k == "language" then
- v = gsub(lower(v),"[^a-z0-9]","")
+ local v = gsub(lower(value),"[^a-z0-9]","")
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]","")
+ local v = gsub(lower(value),"[^a-z0-9]","")
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)
- if type(b) == "nil" then
- v = tonumber(v) or lower(v)
+ local uk = usedfeatures[key]
+ local uv = uk[value]
+ if uv then
+ -- report_checks("feature value %q first seen at %q",value,key)
+ else
+ if type(value) == "string" then
+ local b = is_boolean(value)
+ if type(b) == "nil" then
+ uv = tonumber(value) or lower(value)
+ else
+ uv = b
+ end
else
- v = b
+ uv = v
end
+ if not rawget(features,k) then
+ k = rawget(verbosefeatures,k) or k
+ end
+ local c = checkers[k]
+ if c then
+ uv = c(uv) or vc
+ end
+ uk[value] = uv
end
- if not rawget(features,k) then
- k = rawget(verbosefeatures,k) or k
- end
- local c = checkers[k]
- h[k] = c and c(v) or v
+ h[k] = uv
end
end
return h
diff --git a/tex/context/base/font-pat.lua b/tex/context/base/font-pat.lua
index b91502c74..50d99f668 100644
--- a/tex/context/base/font-pat.lua
+++ b/tex/context/base/font-pat.lua
@@ -6,11 +6,13 @@ if not modules then modules = { } end modules ['font-pat'] = {
license = "see context related readme files"
}
+-- This functiononality is nowadays provided via lfg files so what you see here
+-- is more an example.
+
local match, lower = string.match, string.lower
--- older versions of latin modern didn't have the designsize set
--- so for them we get it from the name
--- reporter moved to elsewhere
+-- Older versions of latin modern didn't have the designsize set so for them we
+-- get it from the name reporter moved to elsewhere.
local fonts = fonts
local otf = fonts.handlers.otf
@@ -32,9 +34,9 @@ register("after","migrate metadata","^lmroman", patch)
register("after","migrate metadata","^lmsans", patch)
register("after","migrate metadata","^lmtypewriter",patch)
--- for some reason (either it's a bug in the font, or it's
--- a problem in the library) the palatino arabic fonts don't
--- have the mkmk features properly set up
+-- For some reason (either it's a bug in the font, or it's a problem in the
+-- library) the palatino arabic fonts don't have the mkmk features properly
+-- set up.
local function patch(data,filename)
local gpos = data.gpos
diff --git a/tex/context/base/font-pre.mkiv b/tex/context/base/font-pre.mkiv
index 141bfd2ff..8d3edb9ec 100644
--- a/tex/context/base/font-pre.mkiv
+++ b/tex/context/base/font-pre.mkiv
@@ -169,7 +169,35 @@
\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]
+\definecolor[font:rest][b=.75,g=.75] % [c=.75]
+
+\definecolor[trace:r][r=.75,t=.5,a=1]
+\definecolor[trace:g][g=.75,t=.5,a=1]
+\definecolor[trace:b][b=.75,t=.5,a=1]
+\definecolor[trace:c][c=.75,t=.5,a=1]
+\definecolor[trace:m][m=.75,t=.5,a=1]
+\definecolor[trace:y][y=.75,t=.5,a=1]
+\definecolor[trace:s][s=.75,t=.5,a=1]
+\definecolor[trace:o][r=1,g=.6,b=.1,t=.5,a=1]
+
+\definecolor[trace:dr][r=.75,t=.75,a=1]
+\definecolor[trace:dg][g=.75,t=.75,a=1]
+\definecolor[trace:db][b=.75,t=.75,a=1]
+\definecolor[trace:dc][c=.75,t=.75,a=1]
+\definecolor[trace:dm][m=.75,t=.75,a=1]
+\definecolor[trace:dy][y=.75,t=.75,a=1]
+\definecolor[trace:ds][s=.75,t=.75,a=1]
+\definecolor[trace:do][r=1,g=.6,b=.1,t=.75,a=1]
+
+\definecolor[font:1] [r=.75]
+\definecolor[font:2] [g=.75]
+\definecolor[font:3] [b=.75]
+\definecolor[font:4] [r=.75,g=.75]
+\definecolor[font:5] [r=.75,b=.75]
+\definecolor[font:6] [b=.75,g=.75]
+\definecolor[font:7] [r=.75]
+\definecolor[font:8] [g=.75]
+\definecolor[font:9] [b=.75]
%D Now we're up to some definitions.
diff --git a/tex/context/base/font-run.mkiv b/tex/context/base/font-run.mkiv
index b346de5e1..66f1acc91 100644
--- a/tex/context/base/font-run.mkiv
+++ b/tex/context/base/font-run.mkiv
@@ -13,7 +13,7 @@
%C details.
%D [This code is hooked into the core macros and saves some
-%D format space.]
+%D format space. It needs a cleanup.]
\unprotect
@@ -31,7 +31,7 @@
{\doifnot{[\fontclass]}\title
{\edef\title{[\fontclass]\space\title}}}}
-\gdef\showbodyfont
+\unexpanded\gdef\showbodyfont
{\dosingleempty\doshowbodyfont}
\gdef\doshowbodyfont[#1]%
@@ -40,9 +40,9 @@
{\dosetshowfonttitle{#1}%
\def\bigstrut##1##2%
{\hbox{\vrule
- \!!height##1\strutht
- \!!depth ##2\strutdp
- \!!width \zeropoint}}
+ \s!height##1\strutht
+ \s!depth ##2\strutdp
+ \s!width \zeropoint}}
\def\next##1##2##3%
{&&##1&&##2\tf##3&&##2\sc##3%
&&##2\sl##3&&##2\it##3&&##2\bf##3&&##2\bs##3&&##2\bi##3%
@@ -50,7 +50,7 @@
&&##2\tfa##3&&##2\tfb##3&&##2\tfc##3&&##2\tfd##3&\cr}%
\halign to \localhsize
{\bigstrut{1.5}{2}##&\vrule##
- \tabskip=\!!zeropoint \!!plus 1fill
+ \tabskip\zeropoint \s!plus 1\s!fill
&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
@@ -58,7 +58,7 @@
&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
&\hfil##\hfil&\vrule##&\hfil##\hfil&##\vrule
- \tabskip=\!!zeropoint\cr
+ \tabskip=\zeropoint\cr
\noalign{\hrule}
&\multispan{29}{\vrule\hfil\tttf\strut\title\hfil
\llap{\string\mr\hbox to 1em{\hss:\hss}$\mr \languageparameter\c!text$\quad}\vrule}\cr
@@ -69,7 +69,7 @@
\noalign{\hrule}}}
\ifinsidefloat\else\stopbaselinecorrection\fi}
-\gdef\showbodyfontenvironment
+\unexpanded\gdef\showbodyfontenvironment
{\dosingleempty\doshowbodyfontenvironment}
\gdef\doshowbodyfontenvironment[#1]%
@@ -89,7 +89,7 @@
\noalign{\hrule}}
\halign to \localhsize
{##&\vrule##\strut
- \tabskip=\!!zeropoint \!!plus 1fill
+ \tabskip=\zeropoint \s!plus 1\s!fill
&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##&\hfil##\hfil&\vrule##
&\hfil##\hfil&\vrule##&\hfil##\hfil&##\vrule
@@ -104,7 +104,7 @@
\@EA\globalprocesscommalist\@EA[\bodyfontenvironmentlist]\next}}
\ifinsidefloat\else\stopbaselinecorrection\fi}
-\gdef\showfont
+\unexpanded\gdef\showfont
{\dodoubleempty\doshowfont}
\gdef\doshowfont[#1][#2]%
@@ -132,7 +132,6 @@
\gdef\dodoshowfont#1#2%
{\bgroup
\edef\charplane{\number#2}%
- \boxrulewidth=.1pt
\iffirstargument
% \definefont[\s!dummy][#1]\dummy
\else\ifdim2.5em>.05\hsize \tx
@@ -159,7 +158,7 @@
\donetrue \else \donefalse
\fi
\else
- \setbox\scratchbox\hbox{\gray\vrule\!!width1ex\!!height.5ex\!!depth.5ex}%
+ \setbox\scratchbox\hbox{\gray\vrule\s!width1ex\s!height.5ex\s!depth.5ex}%
\fi
\startoverlay
{\tf\vbox to 2.5em
@@ -206,9 +205,9 @@
% \showfontstyle[modern][rm][tf][all] % #2, #3 and #4 can be 'all'
-\gdef\showfontstyle {\dodoubleempty \dodoshowfontstyle}
-\gdef\redoshowfontstyle {\dotripleempty \dododoshowfontstyle}
-\gdef\redodoshowfontstyle{\doquadrupleempty\dodododoshowfontstyle}
+\unexpanded\gdef\showfontstyle {\dodoubleempty \dodoshowfontstyle}
+\unexpanded\gdef\redoshowfontstyle {\dotripleempty \dododoshowfontstyle}
+\unexpanded\gdef\redodoshowfontstyle{\doquadrupleempty\dodododoshowfontstyle}
% no lists any more, so no 'all' any longer
@@ -254,10 +253,10 @@
\processcommalist[#2]\docommand
\egroup}
-\gdef\showligature#1%
+\unexpanded\gdef\showligature#1%
{\hbox{\type{#1}\enspace\red\ruledhbox{\black#1}}}
-\gdef\showligatures[#1]%
+\unexpanded\gdef\showligatures[#1]%
{\ifx\starttabulate\undefined
\@@onlyenglish\showligatures
\else
@@ -273,7 +272,7 @@
\egroup
\fi}
-\gdef\showfontstrip
+\unexpanded\gdef\showfontstrip
{\dosingleempty\doshowfontstrip}
\gdef\doshowfontstrip[#1]%
@@ -310,9 +309,9 @@
\egroup
\fi}
-\ifx\databox\undefined \newbox\databox \fi
+\ifdefined\databox \else \newbox\databox \fi
-\gdef\testminimalbaseline#1%
+\unexpanded\gdef\testminimalbaseline#1%
{\setbox\databox\ruledhbox{#1}%
\scratchdimen\ht\databox
\advance\scratchdimen\dp\databox
@@ -332,7 +331,7 @@
\noexpand \NC (\ifdim\scratchdimen>\baselineskip not \fi ok)
\noexpand \NC \noexpand \NR }}
-\gdef\showminimalbaseline
+\unexpanded\gdef\showminimalbaseline
{\ifx\starttabulate\undefined
\@@onlyenglish\showminimalbaseline
\else
@@ -343,20 +342,20 @@
\stoptabulate
\fi}
-\gdef\showkerning#1%
+\unexpanded\gdef\showkerning#1%
{\bgroup
\let\MPfshowcommand\ruledhbox
\setMPtext\s!dummy{#1}%
\startMPcode draw textext(\MPstring\s!dummy);\stopMPcode
\egroup}
-\gdef\showcharratio
+\unexpanded\gdef\showcharratio
{\dowithnextboxcontent
{\switchtobodyfont[10pt]}%
{(\withoutpt\the\nextboxht,\withoutpt\the\nextboxdp)}%
\hbox}
-\gdef\showfontparameters
+\unexpanded\gdef\showfontparameters
{\starttabulate[|tl|l|]
\NC slantperpoint \NC \the\fontslantperpoint \font \NC\NR
\NC interwordspace \NC \the\fontinterwordspace \font \NC\NR
diff --git a/tex/context/base/font-set.mkvi b/tex/context/base/font-set.mkvi
index 8e4044267..c5450a152 100644
--- a/tex/context/base/font-set.mkvi
+++ b/tex/context/base/font-set.mkvi
@@ -121,7 +121,7 @@
\unexpanded\def\font_preloads_fourth_stage
{\begingroup
%ifzeropt\fontcharwd\font\number`!\relax
- \setbox\scratchbox\hbox{context}%
+ \setbox\scratchbox\hbox{checking fonts}%
\ifzeropt\wd\scratchbox
\writeline
\writestatus\m!fonts{!! No bodyfont has been defined and no defaults have been}%
diff --git a/tex/context/base/font-sol.lua b/tex/context/base/font-sol.lua
new file mode 100644
index 000000000..b44594349
--- /dev/null
+++ b/tex/context/base/font-sol.lua
@@ -0,0 +1,898 @@
+if not modules then modules = { } end modules ['font-sol'] = { -- this was: node-spl
+ version = 1.001,
+ comment = "companion to font-sol.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This module is dedicated to the oriental tex project and for
+-- the moment is too experimental to be publicly supported.
+--
+-- We could cache solutions: say that we store the featureset and
+-- all 'words' -> replacement ... so we create a large solution
+-- database (per font)
+--
+-- This module can be optimized by using a dedicated dynamics handler
+-- but I'll only do that when the rest of the code is stable.
+--
+-- Todo: bind setups to paragraph.
+
+local gmatch, concat, format, remove = string.gmatch, table.concat, string.format, table.remove
+local next, tostring, tonumber = next, tostring, tonumber
+local insert, remove = table.insert, table.remove
+local utfchar = utf.char
+local random = math.random
+
+local utilities, logs, statistics, fonts, trackers = utilities, logs, statistics, fonts, trackers
+local interfaces, commands, attributes = interfaces, commands, attributes
+local nodes, node, tex = nodes, node, tex
+
+local trace_split = false trackers.register("builders.paragraphs.solutions.splitters.splitter", function(v) trace_split = v end)
+local trace_optimize = false trackers.register("builders.paragraphs.solutions.splitters.optimizer", function(v) trace_optimize = v end)
+local trace_colors = false trackers.register("builders.paragraphs.solutions.splitters.colors", function(v) trace_colors = v end)
+local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end)
+
+local report_solutions = logs.reporter("fonts","solutions")
+local report_splitters = logs.reporter("fonts","splitters")
+local report_optimizers = logs.reporter("fonts","optimizers")
+
+local variables = interfaces.variables
+
+local v_normal = variables.normal
+local v_reverse = variables.reverse
+local v_preroll = variables.preroll
+local v_random = variables.random
+local v_split = variables.split
+
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local find_node_tail = node.tail or node.slide
+local free_node = node.free
+local free_nodelist = node.flush_list
+local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+local copy_nodelist = node.copy_list
+local traverse_nodes = node.traverse
+local traverse_ids = node.traverse_id
+local protect_glyphs = nodes.handlers.protectglyphs or node.protect_glyphs
+local hpack_nodes = node.hpack
+local insert_node_before = node.insert_before
+local insert_node_after = node.insert_after
+local repack_hlist = nodes.repackhlist
+local nodes_to_utf = nodes.listtoutf
+
+local setnodecolor = nodes.tracers.colors.set
+
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
+local kerncodes = nodes.kerncodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+local hlist_code = nodecodes.hlist
+local whatsit_code = nodecodes.whatsit
+
+local fontkern_code = kerncodes.fontkern
+
+local localpar_code = whatsitcodes.localpar
+local dir_code = whatsitcodes.dir
+local userdefined_code = whatsitcodes.userdefined
+
+local nodepool = nodes.pool
+local tasks = nodes.tasks
+local usernodeids = nodepool.userids
+
+local new_textdir = nodepool.textdir
+local new_usernumber = nodepool.usernumber
+local new_glue = nodepool.glue
+local new_leftskip = nodepool.leftskip
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local process_characters = nodes.handlers.characters
+local inject_kerns = nodes.injections.handler
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local setfontdynamics = fonthashes.setdynamics
+local fontprocesses = fonthashes.processes
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local parbuilders = builders.paragraphs
+parbuilders.solutions = parbuilders.solutions or { }
+local parsolutions = parbuilders.solutions
+parsolutions.splitters = parsolutions.splitters or { }
+local splitters = parsolutions.splitters
+
+local solutions = { } -- attribute sets
+local registered = { } -- backmapping
+splitters.registered = registered
+
+local a_split = attributes.private('splitter')
+
+local preroll = true
+local criterium = 0
+local randomseed = nil
+local optimize = nil -- set later
+local variant = v_normal
+local splitwords = true
+
+local cache = { }
+local variants = { }
+local max_less = 0
+local max_more = 0
+
+local stack = { }
+
+local dummy = {
+ attribute = unsetvalue,
+ randomseed = 0,
+ criterium = 0,
+ preroll = false,
+ optimize = nil,
+ splitwords = false,
+ variant = v_normal,
+}
+
+local function checksettings(r,settings)
+ local s = r.settings
+ local method = settings_to_hash(settings.method or "")
+ local optimize, preroll, splitwords
+ for k, v in next, method do
+ if k == v_preroll then
+ preroll = true
+ elseif k == v_split then
+ splitwords = true
+ elseif variants[k] then
+ variant = k
+ optimize = variants[k] -- last one wins
+ end
+ end
+ r.randomseed = tonumber(settings.randomseed) or s.randomseed or r.randomseed or 0
+ r.criterium = tonumber(settings.criterium ) or s.criterium or r.criterium or 0
+ r.preroll = preroll or false
+ r.splitwords = splitwords or false
+ r.optimize = optimize or s.optimize or r.optimize or variants[v_normal]
+end
+
+local function pushsplitter(name,settings)
+ local r = name and registered[name]
+ if r then
+ if settings then
+ checksettings(r,settings)
+ end
+ else
+ r = dummy
+ end
+ insert(stack,r)
+ -- brr
+ randomseed = r.randomseed or 0
+ criterium = r.criterium or 0
+ preroll = r.preroll or false
+ optimize = r.optimize or nil
+ splitwords = r.splitwords or nil
+ --
+ texsetattribute(a_split,r.attribute)
+ return #stack
+end
+
+local function popsplitter()
+ remove(stack)
+ local n = #stack
+ local r = stack[n] or dummy
+ --
+ randomseed = r.randomseed or 0
+ criterium = r.criterium or 0
+ preroll = r.preroll or false
+ optimize = r.optimize or nil
+ --
+ texsetattribute(a_split,r.attribute)
+ return n
+end
+
+local contextsetups = fonts.specifiers.contextsetups
+
+local function convert(featuresets,name,list)
+ if list then
+ local numbers = { }
+ local nofnumbers = 0
+ for i=1,#list do
+ local feature = list[i]
+ local fs = featuresets[feature]
+ local fn = fs and fs.number
+ if not fn then
+ -- fall back on global features
+ fs = contextsetups[feature]
+ fn = fs and fs.number
+ end
+ if fn then
+ nofnumbers = nofnumbers + 1
+ numbers[nofnumbers] = fn
+ if trace_goodies or trace_optimize then
+ report_solutions("solution %s of '%s' uses feature '%s' with number %s",i,name,feature,fn)
+ end
+ else
+ report_solutions("solution %s has an invalid feature reference '%s'",i,name,tostring(feature))
+ end
+ end
+ return nofnumbers > 0 and numbers
+ end
+end
+
+local function initialize(goodies)
+ local solutions = goodies.solutions
+ if solutions then
+ local featuresets = goodies.featuresets
+ local goodiesname = goodies.name
+ if trace_goodies or trace_optimize then
+ report_solutions("checking solutions in '%s'",goodiesname)
+ end
+ for name, set in next, solutions do
+ set.less = convert(featuresets,name,set.less)
+ set.more = convert(featuresets,name,set.more)
+ end
+ end
+end
+
+fonts.goodies.register("solutions",initialize)
+
+function splitters.define(name,settings)
+ local goodies = settings.goodies
+ local solution = settings.solution
+ local less = settings.less
+ local more = settings.more
+ local less_set, more_set
+ local l = less and settings_to_array(less)
+ local m = more and settings_to_array(more)
+ if goodies then
+ goodies = fonts.goodies.load(goodies) -- also in tfmdata
+ if goodies then
+ local featuresets = goodies.featuresets
+ local solution = solution and goodies.solutions[solution]
+ if l and #l > 0 then
+ less_set = convert(featuresets,name,less) -- take from settings
+ else
+ less_set = solution and solution.less -- take from goodies
+ end
+ if m and #m > 0 then
+ more_set = convert(featuresets,name,more) -- take from settings
+ else
+ more_set = solution and solution.more -- take from goodies
+ end
+ end
+ else
+ if l then
+ local n = #less_set
+ for i=1,#l do
+ local ss = contextsetups[l[i]]
+ if ss then
+ n = n + 1
+ less_set[n] = ss.number
+ end
+ end
+ end
+ if m then
+ local n = #more_set
+ for i=1,#m do
+ local ss = contextsetups[m[i]]
+ if ss then
+ n = n + 1
+ more_set[n] = ss.number
+ end
+ end
+ end
+ end
+ if trace_optimize then
+ report_solutions("defining solutions '%s', less: '%s', more: '%s'",name,concat(less_set or {}," "),concat(more_set or {}," "))
+ end
+ local nofsolutions = #solutions + 1
+ local t = {
+ solution = solution,
+ less = less_set or { },
+ more = more_set or { },
+ settings = settings, -- for tracing
+ attribute = nofsolutions,
+ }
+ solutions[nofsolutions] = t
+ registered[name] = t
+ return nofsolutions
+end
+
+local nofwords, noftries, nofadapted, nofkept, nofparagraphs = 0, 0, 0, 0, 0
+
+local splitter_one = usernodeids["splitters.one"]
+local splitter_two = usernodeids["splitters.two"]
+
+local a_word = attributes.private('word')
+local a_fontkern = attributes.private('fontkern')
+
+local encapsulate = false
+
+directives.register("builders.paragraphs.solutions.splitters.encapsulate", function(v)
+ encapsulate = v
+end)
+
+function splitters.split(head)
+ -- quite fast
+ local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0
+ cache, max_less, max_more = { }, 0, 0
+ local function flush() -- we can move this
+ local font = start.font
+ local last = stop.next
+ local list = last and copy_nodelist(start,last) or copy_nodelist(start)
+ local n = #cache + 1
+ if encapsulate then
+ local user_one = new_usernumber(splitter_one,n)
+ local user_two = new_usernumber(splitter_two,n)
+ head, start = insert_node_before(head,start,user_one)
+ insert_node_after(head,stop,user_two)
+ else
+ local current = start
+ while true do
+ set_attribute(current,a_word,n)
+ if current == stop then
+ break
+ else
+ current = current.next
+ end
+ end
+ end
+ if rlmode == "TRT" or rlmode == "+TRT" then
+ local dirnode = new_textdir("+TRT")
+ list.prev = dirnode
+ dirnode.next = list
+ list = dirnode
+ end
+ local c = {
+ original = list,
+ attribute = attribute,
+ direction = rlmode,
+ font = font
+ }
+ if trace_split then
+ report_splitters("cached %4i: font: %s, attribute: %s, direction: %s, word: %s",
+ n, font, attribute, nodes_to_utf(list,true), rlmode and "r2l" or "l2r")
+ end
+ cache[n] = c
+ local solution = solutions[attribute]
+ local l, m = #solution.less, #solution.more
+ if l > max_less then max_less = l end
+ if m > max_more then max_more = m end
+ start, stop, done = nil, nil, true
+ end
+ while current do -- also nextid
+ local next = current.next
+ local id = current.id
+ if id == glyph_code then
+ if current.subtype < 256 then
+ local a = has_attribute(current,a_split)
+ if not a then
+ start, stop = nil, nil
+ elseif not start then
+ start, stop, attribute = current, current, a
+ elseif a ~= attribute then
+ start, stop = nil, nil
+ else
+ stop = current
+ end
+ end
+ elseif id == disc_code then
+ if splitwords then
+ if start then
+ flush()
+ end
+ elseif start and next and next.id == glyph_code and next.subtype < 256 then
+ -- beware: we can cross future lines
+ stop = next
+ else
+ start, stop = nil, nil
+ end
+ elseif id == whatsit_code then
+ if start then
+ flush()
+ end
+ local subtype = current.subtype
+ if subtype == dir_code or subtype == localpar_code then
+ rlmode = current.dir
+ end
+ else
+ if start then
+ flush()
+ end
+ end
+ current = next
+ end
+ if start then
+ flush()
+ end
+ nofparagraphs = nofparagraphs + 1
+ nofwords = nofwords + #cache
+ return head, done
+end
+
+local function collect_words(list) -- can be made faster for attributes
+ local words, w, word = { }, 0, nil
+ if encapsulate then
+ for current in traverse_ids(whatsit_code,list) do
+ if current.subtype == userdefined_code then -- hm
+ local user_id = current.user_id
+ if user_id == splitter_one then
+ word = { current.value, current, current }
+ w = w + 1
+ words[w] = word
+ elseif user_id == splitter_two then
+ if word then
+ word[3] = current
+ else
+ -- something is wrong
+ end
+ end
+ end
+ end
+ else
+ local current, first, last, index = list, nil, nil, nil
+ while current do
+ -- todo: disc and kern
+ local id = current.id
+ if id == glyph_code or id == disc_code then
+ local a = has_attribute(current,a_word)
+ if a then
+ if a == index then
+ -- same word
+ last = current
+ elseif index then
+ w = w + 1
+ words[w] = { index, first, last }
+ first = current
+ last = current
+ index = a
+ elseif first then
+ last = current
+ index = a
+ else
+ first = current
+ last = current
+ index = a
+ end
+ elseif index then
+ if first then
+ w = w + 1
+ words[w] = { index, first, last }
+ end
+ index = nil
+ first = nil
+ elseif trace_split then
+ if id == disc_code then
+ report_splitters("skipped: disc node")
+ else
+ report_splitters("skipped: %s",utfchar(current.char))
+ end
+ end
+ elseif id == kern_code and (current.subtype == fontkern_code or has_attribute(current,a_fontkern)) then
+ if first then
+ last = current
+ else
+ first = current
+ last = current
+ end
+ elseif index then
+ w = w + 1
+ words[w] = { index, first, last }
+ index = nil
+ first = nil
+ if id == disc_node then
+ if trace_split then
+ report_splitters("skipped disc node")
+ end
+ end
+ end
+ current = current.next
+ end
+ if index then
+ w = w + 1
+ words[w] = { index, first, last }
+ end
+ if trace_split then
+ for i=1,#words do
+ local w = words[i]
+ local n, f, l = w[1], w[2], w[3]
+ local c = cache[n]
+ if c then
+ report_splitters("found %4i: word: %s, cached: %s",n,nodes_to_utf(f,true,true,l),nodes_to_utf(c.original,true))
+ else
+ report_splitters("found %4i: word: %s, not in cache",n,nodes_to_utf(f,true,true,l))
+ end
+ end
+ end
+ end
+ return words, list -- check for empty (elsewhere)
+end
+
+-- we could avoid a hpack but hpack is not that slow
+
+local function doit(word,list,best,width,badness,line,set,listdir)
+ local changed = 0
+ local n = word[1]
+ local found = cache[n]
+ if found then
+ local h, t
+ if encapsulate then
+ h = word[2].next -- head of current word
+ t = word[3].prev -- tail of current word
+ else
+ h = word[2]
+ t = word[3]
+ end
+ if splitwords then
+ -- there are no lines crossed in a word
+ else
+ local ok = false
+ local c = h
+ while c do
+ if c == t then
+ ok = true
+ break
+ else
+ c = c.next
+ end
+ end
+ if not ok then
+ report_solutions("skipping hyphenated word (for now)")
+ -- todo: mark in words as skipped, saves a bit runtime
+ return false, changed
+ end
+ end
+ local original, attribute, direction = found.original, found.attribute, found.direction
+ local solution = solutions[attribute]
+ local features = solution and solution[set]
+ if features then
+ local featurenumber = features[best] -- not ok probably
+ if featurenumber then
+ noftries = noftries + 1
+ local first = copy_nodelist(original)
+ if not trace_colors then
+ for n in traverse_nodes(first) do -- maybe fast force so no attr needed
+ set_attribute(n,0,featurenumber) -- this forces dynamics
+ end
+ elseif set == "less" then
+ for n in traverse_nodes(first) do
+ setnodecolor(n,"font:isol") -- yellow
+ set_attribute(n,0,featurenumber)
+ end
+ else
+ for n in traverse_nodes(first) do
+ setnodecolor(n,"font:medi") -- green
+ set_attribute(n,0,featurenumber)
+ end
+ end
+ local font = found.font
+ -- local dynamics = found.dynamics
+ -- local shared = fontdata[font].shared
+ -- if not dynamics then -- we cache this
+ -- dynamics = shared.dynamics
+ -- found.dynamics = dynamics
+ -- end
+ -- local processors = found[featurenumber]
+ -- if not processors then -- we cache this too
+ -- processors = fonts.handlers.otf.setdynamics(font,featurenumber)
+ -- found[featurenumber] = processors
+ -- end
+ local setdynamics = setfontdynamics[font]
+ if setdynamics then
+ local processes = setdynamics(font,featurenumber)
+ for i=1,#processes do -- often more than 1
+ first = processes[i](first,font,featurenumber)
+ end
+ else
+ report_solutions("fatal error, no dynamics for font %s",font)
+ end
+ first = inject_kerns(first)
+ if first.id == whatsit_code then
+ local temp = first
+ first = first.next
+ free_node(temp)
+ end
+ local last = find_node_tail(first)
+ -- replace [u]h->t by [u]first->last
+ local prev = h.prev
+ local next = t.next
+ prev.next = first
+ first.prev = prev
+ if next then
+ last.next = next
+ next.prev = last
+ end
+ -- check new pack
+ local temp, b = repack_hlist(list,width,'exactly',listdir)
+ if b > badness then
+ if trace_optimize then
+ report_optimizers("line %s, badness before: %s, after: %s, criterium: %s -> quit",line,badness,b,criterium)
+ end
+ -- remove last insert
+ prev.next = h
+ h.prev = prev
+ if next then
+ t.next = next
+ next.prev = t
+ else
+ t.next = nil
+ end
+ last.next = nil
+ free_nodelist(first)
+ else
+ if trace_optimize then
+ report_optimizers("line %s, badness before: %s, after: %s, criterium: %s -> continue",line,badness,b,criterium)
+ end
+ -- free old h->t
+ t.next = nil
+ free_nodelist(h) -- somhow fails
+ if not encapsulate then
+ word[2] = first
+ word[3] = last
+ end
+ changed, badness = changed + 1, b
+ end
+ if b <= criterium then
+ return true, changed
+ end
+ end
+ end
+ end
+ return false, changed
+end
+
+-- We repeat some code but adding yet another layer of indirectness is not
+-- making things better.
+
+variants[v_normal] = function(words,list,best,width,badness,line,set,listdir)
+ local changed = 0
+ for i=1,#words do
+ local done, c = doit(words[i],list,best,width,badness,line,set,listdir)
+ changed = changed + c
+ if done then
+ break
+ end
+ end
+ if changed > 0 then
+ nofadapted = nofadapted + 1
+ -- todo: get rid of pack when ok because we already have packed and we only need the last b
+ local list, b = repack_hlist(list,width,'exactly',listdir)
+ return list, true, changed, b -- badness
+ else
+ nofkept = nofkept + 1
+ return list, false, 0, badness
+ end
+end
+
+variants[v_reverse] = function(words,list,best,width,badness,line,set,listdir)
+ local changed = 0
+ for i=#words,1,-1 do
+ local done, c = doit(words[i],list,best,width,badness,line,set,listdir)
+ changed = changed + c
+ if done then
+ break
+ end
+ end
+ if changed > 0 then
+ nofadapted = nofadapted + 1
+ -- todo: get rid of pack when ok because we already have packed and we only need the last b
+ local list, b = repack_hlist(list,width,'exactly',listdir)
+ return list, true, changed, b -- badness
+ else
+ nofkept = nofkept + 1
+ return list, false, 0, badness
+ end
+end
+
+variants[v_random] = function(words,list,best,width,badness,line,set,listdir)
+ local changed = 0
+ while #words > 0 do
+ local done, c = doit(remove(words,random(1,#words)),list,best,width,badness,line,set,listdir)
+ changed = changed + c
+ if done then
+ break
+ end
+ end
+ if changed > 0 then
+ nofadapted = nofadapted + 1
+ -- todo: get rid of pack when ok because we already have packed and we only need the last b
+ local list, b = repack_hlist(list,width,'exactly',listdir)
+ return list, true, changed, b -- badness
+ else
+ nofkept = nofkept + 1
+ return list, false, 0, badness
+ end
+end
+
+local function show_quality(current,what,line)
+ local set = current.glue_set
+ local sign = current.glue_sign
+ local order = current.glue_order
+ local amount = set * ((sign == 2 and -1) or 1)
+ report_optimizers("line %s, %s, amount %s, set %s, sign %s (%s), order %s",line,what,amount,set,sign,how,order)
+end
+
+function splitters.optimize(head)
+ if not optimize then
+ report_optimizers("no optimizer set")
+ return
+ end
+ local nc = #cache
+ if nc == 0 then
+ return
+ end
+ starttiming(splitters)
+ local listdir = nil -- todo ! ! !
+ if randomseed then
+ math.setrandomseedi(randomseed)
+ randomseed = nil
+ end
+ local line = 0
+ local tex_hbadness, tex_hfuzz = tex.hbadness, tex.hfuzz
+ tex.hbadness, tex.hfuzz = 10000, number.maxdimen
+ if trace_optimize then
+ report_optimizers("preroll: %s, variant: %s, preroll criterium: %s, cache size: %s",
+ tostring(preroll),variant,criterium,nc)
+ end
+ for current in traverse_ids(hlist_code,head) do
+ -- report_splitters("before: [%s] => %s",current.dir,nodes.tosequence(current.list,nil))
+ line = line + 1
+ local sign, dir, list, width = current.glue_sign, current.dir, current.list, current.width
+if not encapsulate and list.id == glyph_code then
+ -- nasty .. we always assume a prev being there .. future luatex will always have a leftskip set
+ -- current.list, list = insert_node_before(list,list,new_glue(0))
+ current.list, list = insert_node_before(list,list,new_leftskip(0))
+end
+ local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node
+ if badness > 0 then
+ if sign == 0 then
+ if trace_optimize then
+ report_optimizers("line %s, badness %s, okay",line,badness)
+ end
+ else
+ local set, max
+ if sign == 1 then
+ if trace_optimize then
+ report_optimizers("line %s, badness %s, underfull, trying more",line,badness)
+ end
+ set, max = "more", max_more
+ else
+ if trace_optimize then
+ report_optimizers("line %s, badness %s, overfull, trying less",line,badness)
+ end
+ set, max = "less", max_less
+ end
+ -- we can keep the best variants
+ local lastbest, lastbadness = nil, badness
+ if preroll then
+ local bb, base
+ for i=1,max do
+ if base then
+ free_nodelist(base)
+ end
+ base = copy_nodelist(list)
+ local words = collect_words(base) -- beware: words is adapted
+ for j=i,max do
+ local temp, done, changes, b = optimize(words,base,j,width,badness,line,set,dir)
+ base = temp
+ if trace_optimize then
+ report_optimizers("line %s, alternative: %s.%s, changes: %s, badness %s",line,i,j,changes,b)
+ end
+ bb = b
+ if b <= criterium then
+ break
+ end
+ -- if done then
+ -- break
+ -- end
+ end
+ if bb and bb > criterium then -- needs checking
+ if not lastbest then
+ lastbest, lastbadness = i, bb
+ elseif bb > lastbadness then
+ lastbest, lastbadness = i, bb
+ end
+ else
+ break
+ end
+ end
+ free_nodelist(base)
+ end
+ local words = collect_words(list)
+ for best=lastbest or 1,max do
+ local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir)
+ current.list = temp
+ if trace_optimize then
+ report_optimizers("line %s, alternative: %s, changes: %s, badness %s",line,best,changes,b)
+ end
+ if done then
+ if b <= criterium then -- was == 0
+ protect_glyphs(list)
+ break
+ end
+ end
+ end
+ end
+ else
+ if trace_optimize then
+ report_optimizers("line %s, not bad enough",line)
+ end
+ end
+ -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus
+ current.list = hpack_nodes(current.list,width,'exactly',listdir)
+ -- report_splitters("after: [%s] => %s",temp.dir,nodes.tosequence(temp.list,nil))
+ end
+ for i=1,nc do
+ local ci = cache[i]
+ free_nodelist(ci.original)
+ end
+ cache = { }
+ tex.hbadness, tex.hfuzz = tex_hbadness, tex_hfuzz
+ stoptiming(splitters)
+end
+
+statistics.register("optimizer statistics", function()
+ if nofwords > 0 then
+ local elapsed = statistics.elapsedtime(splitters)
+ local average = noftries/elapsed
+ return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %0.3f seconds used, %s adapted, %0.1f lines per second",
+ nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average)
+ end
+end)
+
+-- we could use a stack
+
+local enableaction = tasks.enableaction
+local disableaction = tasks.disableaction
+
+local function enable()
+ enableaction("processors", "builders.paragraphs.solutions.splitters.split")
+ enableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
+end
+
+local function disable()
+ disableaction("processors", "builders.paragraphs.solutions.splitters.split")
+ disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
+end
+
+function splitters.start(name,settings)
+ if pushsplitter(name,settings) == 1 then
+ enable()
+ end
+end
+
+function splitters.stop()
+ if popsplitter() == 0 then
+ disable()
+ end
+end
+
+function splitters.set(name,settings)
+ if #stack > 0 then
+ stack = { }
+ else
+ enable()
+ end
+ pushsplitter(name,settings) -- sets attribute etc
+end
+
+function splitters.reset()
+ if #stack > 0 then
+ stack = { }
+ popsplitter() -- resets attribute etc
+ disable()
+ end
+end
+
+-- interface
+
+commands.definefontsolution = splitters.define
+commands.startfontsolution = splitters.start
+commands.stopfontsolution = splitters.stop
+commands.setfontsolution = splitters.set
+commands.resetfontsolution = splitters.reset
diff --git a/tex/context/base/node-spl.mkiv b/tex/context/base/font-sol.mkvi
index 3630212af..b40e37ced 100644
--- a/tex/context/base/node-spl.mkiv
+++ b/tex/context/base/font-sol.mkvi
@@ -1,8 +1,8 @@
%D \module
-%D [ file=node-spl,
+%D [ file=font-sol,
%D version=2009.05.19,
-%D title=\CONTEXT\ Node Macros,
-%D subtitle=Splitters,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Solutions,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
@@ -13,9 +13,7 @@
\writestatus{loading}{ConTeXt Node Support / Splitters}
-\registerctxluafile{node-spl}{1.001}
-
-\definesystemattribute[splitter][public]
+% todo: pass color for tracing
%D This module is specially made for the oriental \TEX\ project. The working is as
%D follows (and tuned for fonts like Idris' Husayni. The following method came to
@@ -74,36 +72,47 @@
%D \disabletrackers[parbuilders.solutions.splitters.colors]
%D \stoptyping
+\registerctxluafile{font-sol}{1.001}
+
\unprotect
-\newtoks\everysetupfontsolutions
+\definesystemattribute[splitter][public]
-\unexpanded\def\definefontsolution
- {\dodoubleargument\dodefinefontsolution}
+\installcorenamespace{fontsolution}
-\def\dodefinefontsolution[#1][#2]% we could set the attribute at the lua end
- {\setxvalue{\??fu:#1}{\attribute\splitterattribute\ctxlua{builders.paragraphs.solutions.splitters.define("#1","#2")}\relax}}
+\installcommandhandler \??fontsolution {fontsolution} \??fontsolution
-\unexpanded\def\setfontsolution[#1]%
- {\ctxlua{builders.paragraphs.solutions.splitters.enable()}%
- \csname\??fu:#1\endcsname}
+\let\setupfontsolutions\setupfontsolution
-\unexpanded\def\resetfontsolution
- {\ctxlua{builders.paragraphs.solutions.splitters.disable()}%
- \attribute\splitterattribute\attributeunsetvalue}
+\appendtoks
+ \ctxcommand{definefontsolution("\currentfontsolution",{ % these are frozen
+ goodies = "\fontsolutionparameter\s!goodies",
+ solution = "\fontsolutionparameter\c!solution",
+ less = "\fontsolutionparameter\c!less",
+ more = "\fontsolutionparameter\c!more",
+ })}
+\to \everydefinefontsolution
-\letvalue{\??fu:\v!reset}\resetfontsolution
+\unexpanded\def\setfontsolution[#solution]% just one
+ {\edef\currentfontsolution{#solution}%
+ \ctxcommand{setfontsolution("\currentfontsolution",{
+ method = "\fontsolutionparameter\c!method",
+ criterium = "\fontsolutionparameter\c!criterium",
+ % randomseed = "\fontsolutionparameter\c!random",
+ })}}
-\unexpanded\def\setupfontsolutions[#1]%
- {\getparameters[\??fu][#1]%
- \the\everysetupfontsolutions}
+\unexpanded\def\resetfontsolution % resets all
+ {\ctxcommand{resetfontsolution()}%
+ \let\currentfontsolution\empty}
-\appendtoks
- \ctxlua{builders.paragraphs.solutions.splitters.setup {
- method = "\@@fumethod",
- criterium = "\@@fucriterium",
- }}%
-\to \everysetupfontsolutions
+\unexpanded\def\startfontsolution % [#1]
+ {\pushmacro\currentfontsolution
+ \setfontsolution}
+
+\unexpanded\def\stopfontsolution
+ {\ifhmode\par\fi
+ \ctxcommand{stopfontsolution()}%
+ \popmacro\currentfontsolution}
% We initialize this module at the \LUA\ end.
%
diff --git a/tex/context/base/font-sty.mkvi b/tex/context/base/font-sty.mkvi
index d8f01afa7..732d2b027 100644
--- a/tex/context/base/font-sty.mkvi
+++ b/tex/context/base/font-sty.mkvi
@@ -84,7 +84,7 @@
% \appendtoks
% \let\groupedcommand\thirdofthreearguments
-% \to \simplifiedcommands
+% \to \everysimplifycommands
%D This command also defines the keyword as command. This means
%D that the example definition of \type{bold} we gave before,
@@ -216,11 +216,19 @@
\installcommandhandler \??style {style} \??style
+\setupstyle
+ [%\c!style=,
+ %\c!color=,
+ \c!method=\v!command]
+
\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
+ \edef\p_method{\styleparameter\c!method}%
+ \ifx\p_method\v!command
+ \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
+ \fi
\to \everydefinestyle
\unexpanded\def\font_styles_apply_start#name%
@@ -242,7 +250,9 @@
\unexpanded\def\font_styles_use_generic#specification%
{\let\currentstyle\s!unknown % reasonable generic tag
- \setupcurrentstyle[\c!style=,\c!color=,#specification]%
+ \letstyleparameter\c!style\empty
+ \letstyleparameter\c!color\empty
+ \setupcurrentstyle[#specification]%
\usestylestyleandcolor\c!style\c!color}
% commands
@@ -251,14 +261,20 @@
\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
+ \ifcsname\??stylecheck#name\endcsname
+ 2% defined as style
+ \else\ifcsname#name\endcsname
+ 1% defined as command
+ \else
+ 3% specification
+ \fi\fi
\endcsname{#name}}
\setvalue{\??styleargument1}#name%
- {\csname#name\endcsname}
+ {\groupedcommand{\csname#name\endcsname}{}}
\setvalue{\??styleargument2}#name%
- {\groupedcommand{\font_styles_use_defined{#name}}{}}
+ {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}}
\setvalue{\??styleargument3}#specification%
{\doifassignmentelse{#specification}\font_styles_assignment\font_styles_direct{#specification}}
@@ -273,7 +289,13 @@
\unexpanded\def\startstyle[#name]%
{\begingroup
\csname\??styleenvironment
- \ifcsname#name\endcsname1\else\ifcsname\??stylecheck#name\endcsname2\else3\fi\fi
+ \ifcsname\??stylecheck#name\endcsname
+ 2% defined as style
+ \else\ifcsname#name\endcsname
+ 1% defined as command
+ \else
+ 3% specification
+ \fi\fi
\endcsname{#name}}
\unexpanded\def\stopstyle
@@ -289,7 +311,7 @@
\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_assignment#specification{\font_styles_use_generic{#specification}}
\def\font_styles_start_direct #specification{\definedfont[#specification]\relax}
%D Still experimental (might even go away).
diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua
index c4f0e948b..d99114998 100644
--- a/tex/context/base/font-syn.lua
+++ b/tex/context/base/font-syn.lua
@@ -15,7 +15,6 @@ 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
local allocate = utilities.storage.allocate
@@ -34,13 +33,13 @@ using a table that has keys filtered from the font related files.</p>
fonts = fonts or { } -- also used elsewhere
-local names = { }
+local names = font.names or allocate { }
fonts.names = names
-names.filters = names.filters or { }
-local filters = names.filters
+local filters = names.filters or { }
+names.filters = filters
-names.data = names.data or { }
+names.data = names.data or allocate { }
names.version = 1.110
names.basename = "names"
@@ -310,8 +309,6 @@ end
local function cleanname(name)
return (gsub(lower(name),"[^%a%d]",""))
- -- once we can load files with utf names, we can play with the following:
- -- return (utfgsub(utfgsub(lower(str),"[^%a%A%d]",""),"%s",""))
end
local function cleanfilename(fullname,defaultsuffix)
diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua
index b1ec7c1de..53ef8dd99 100644
--- a/tex/context/base/font-tfm.lua
+++ b/tex/context/base/font-tfm.lua
@@ -15,22 +15,21 @@ local trace_features = false trackers.register("tfm.features", func
local report_defining = logs.reporter("fonts","defining")
local report_tfm = logs.reporter("fonts","tfm loading")
+local findbinfile = resolvers.findbinfile
+
local fonts = fonts
local handlers = fonts.handlers
local readers = fonts.readers
local constructors = fonts.constructors
local encodings = fonts.encodings
-local tfm = { }
-handlers.tfm = tfm
-
-constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
-
-local findbinfile = resolvers.findbinfile
+local tfm = constructors.newhandler("tfm")
-local tfmfeatures = fonts.constructors.newfeatures("tfm")
+local tfmfeatures = constructors.newfeatures("tfm")
local registertfmfeature = tfmfeatures.register
+constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
+
fonts.formats.tfm = "type1" -- we need to have at least a value here
--[[ldx--
@@ -92,7 +91,7 @@ local function read_from_tfm(specification)
constructors.enhanceparameters(parameters) -- official copies for us
--
if constructors.resolvevirtualtoo then
- fonts.loggers.register(tfmdata,file.extname(filename),specification) -- strange, why here
+ fonts.loggers.register(tfmdata,file.suffix(filename),specification) -- strange, why here
local vfname = findbinfile(specification.name, 'ovf')
if vfname and vfname ~= "" then
local vfdata = font.read_vf(vfname,size) -- not cached, fast enough
diff --git a/tex/context/base/font-tra.mkiv b/tex/context/base/font-tra.mkiv
index 06b861378..e838d4938 100644
--- a/tex/context/base/font-tra.mkiv
+++ b/tex/context/base/font-tra.mkiv
@@ -13,6 +13,8 @@
\unprotect
+\writestatus{loading}{ConTeXt Font Macros / Tracing}
+
%D \macros
%D {showbodyfont}
%D
@@ -82,10 +84,8 @@
\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()}}
+\unexpanded\def\showchardata #1{\ctxcommand{showchardata("#1")}}
+\unexpanded\def\showfontdata {\ctxcommand{showfontparameters()}}
%D \macros
%D {doiffontpresentelse}
@@ -95,7 +95,7 @@
%D \doiffontpresentelse{adam-lindsay-modern-serif}{YES}{NO}
%D \stoptyping
-\def\doiffontpresentelse#1{\ctxcommand{doifelse(fonts.names.exists("#1"))}}
+\unexpanded\def\doiffontpresentelse#1{\ctxcommand{doifelse(fonts.names.exists("#1"))}}
% experimental, maybe this becomes a module
@@ -103,46 +103,46 @@
\unexpanded\def\startotfcollecting{\ctxlua{nodes.tracers.steppers.start()}}
\unexpanded\def\stopotfcollecting {\ctxlua{nodes.tracers.steppers.stop()}}
-\def\resetotfcollecting{\ctxlua{nodes.tracers.steppers.reset()}}
+\unexpanded\def\resetotfcollecting{\ctxlua{nodes.tracers.steppers.reset()}}
% Rather experimental:
%
% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{الضَّرَّ} \page
% \page \showotfcomposition{arabtype*arab-default at 48pt}{-1}{لِلّٰهِ} \page
-\def\showotfstepglyphs#1%
+\unexpanded\def\showotfstepglyphs#1%
{\ctxlua{nodes.tracers.steppers.glyphs(\number\otfcollector,#1)}%
\unhbox\otfcollector}
-\def\otfstepcharcommand#1#2#3% font char class
+\unexpanded\def\otfstepcharcommand#1#2#3% font char class
{\removeunwantedspaces
- \hskip.5em plus .125em\relax
+ \hskip.5\emwidth \s!plus .125\emwidth\relax
\doif{#3}{mark}{\underbar}{U+\hexnumber{#2}}:\ruledhbox{\ctxlua{nodes.tracers.fontchar(#1,#2)}}%
- \hskip.5em plus .125em\relax}
+ \hskip.5\emwidth \s!plus .125\emwidth\relax}
-\def\otfstepmessagecommand#1#2%
+\unexpanded\def\otfstepmessagecommand#1#2%
{\begingroup
\tttf\language\minusone
\veryraggedright
\forgetparindent
\forgeteverypar
- \hangindent1em
+ \hangindent\emwidth
\hangafter\plusone
\dontleavehmode\hbox{\detokenize{#1}}\removeunwantedspaces
\doifsomething{#2}{\break\detokenize{#2}}\endgraf
\endgroup
\blank}
-\def\showotfstepchars#1%
+\unexpanded\def\showotfstepchars#1%
{\ctxlua{nodes.tracers.steppers.codes(#1,"otfstepcharcommand")}}
-\def\showotfstepmessages#1%
+\unexpanded\def\showotfstepmessages#1%
{\ctxlua{nodes.tracers.steppers.messages(#1,"otfstepmessagecommand",true)}}
-\def\showotfstepfeatures
+\unexpanded\def\showotfstepfeatures
{\ctxlua{nodes.tracers.steppers.features()}}
-\def\showotfsteps
+\unexpanded\def\showotfsteps
{\begingroup
\veryraggedright
\forgetparindent
@@ -186,14 +186,24 @@
\newbox\otfcompositionbox
-\def\showotfcomposition#1#2#3% {font*features at size}, rl=-1, text
+% this should go in spac-ali:
+
+\installcorenamespace{otfcompositiondir}
+
+\letvalue{\??otfcompositiondir -1}\righttoleft
+\letvalue{\??otfcompositiondir r2l}\righttoleft
+\letvalue{\??otfcompositiondir l2r}\lefttoright
+\letvalue{\??otfcompositiondir +1}\lefttoright
+\letvalue{\??otfcompositiondir 1}\lefttoright
+
+\unexpanded\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}%
+ \global\setbox\otfcompositionbox\hbox{\definedfont[#1]\relax\getvalue{\??otfcompositiondir#2}\relax#3}%
\stopotfsample
\endgroup}
diff --git a/tex/context/base/font-vf.lua b/tex/context/base/font-vf.lua
index 287d073d6..01d5289f8 100644
--- a/tex/context/base/font-vf.lua
+++ b/tex/context/base/font-vf.lua
@@ -19,8 +19,7 @@ local fastcopy = table.fastcopy
local fonts = fonts
local constructors = fonts.constructors
-local vf = { }
-fonts.handlers.vf = vf
+local vf = constructors.newhandler("vf")
-- general code
diff --git a/tex/context/base/grph-epd.lua b/tex/context/base/grph-epd.lua
index 130907d4e..4f9d46097 100644
--- a/tex/context/base/grph-epd.lua
+++ b/tex/context/base/grph-epd.lua
@@ -22,5 +22,4 @@ function figures.mergegoodies(optionlist)
if all or options[variables.layer] then
codeinjections.mergeviewerlayers()
end
-
end
diff --git a/tex/context/base/grph-epd.mkiv b/tex/context/base/grph-epd.mkiv
index 947128b6b..26c07e731 100644
--- a/tex/context/base/grph-epd.mkiv
+++ b/tex/context/base/grph-epd.mkiv
@@ -22,18 +22,24 @@
\defineoverlay[system:graphics:epdf][\directsetup{system:graphics:epdf}]
\startsetups system:graphics:epdf
- \ctxlua{figures.mergegoodies("\@@efinteraction")}%
+ \ctxlua{figures.mergegoodies("\externalfigureparameter\c!interaction")}%
\reference[\figurereference]{}% todo: dest area
\stopsetups
+\defineframed
+ [system_graphics_epdf]
+ [\c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!background={\v!foreground,system:graphics:epdf}]
+
\def\grph_epdf_add_overlay
{\global\setbox\foundexternalfigure\vbox\bgroup
- \framed[\c!offset=\v!overlay,\c!background={\v!foreground,system:graphics:epdf}]{\box\foundexternalfigure}%
+ \system_graphics_epdf{\box\foundexternalfigure}%
\egroup}
\appendtoks
\iflocation
- \doif\figurefiletype{pdf}{\doifnot\@@efinteraction\v!none\grph_epdf_add_overlay}%
+ \doif\figurefiletype{pdf}{\doifnot{\externalfigureparameter\c!interaction}\v!none\grph_epdf_add_overlay}%
\fi
\to \externalfigurepostprocessors
diff --git a/tex/context/base/grph-fig.mkiv b/tex/context/base/grph-fig.mkiv
index 1908e6445..864bd29fb 100644
--- a/tex/context/base/grph-fig.mkiv
+++ b/tex/context/base/grph-fig.mkiv
@@ -11,351 +11,198 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% ex => ef with proper parent
-
-\writestatus{loading}{ConTeXt Graphic Macros / Figure Handling}
-
\unprotect
-\unexpanded\def\setupexternalfigures
- {\dosingleempty\dosetupexternalfigures}
-
-\def\dosetupexternalfigures[#1]%
- {\getparameters[\??ef][#1]% local settings
- \getparameters[\??ex][#1]% global settings
- \setfigurepathlist} % the path may be used elsewhere too (as in x-res-04)
-
-\presetlocalframed[\??ef]
-
-\newconditional\externalfigurelevel % true=background false=normal
-\newconditional\externalfigureflush % true=place false=ignore
+%D Used in the styledesign manual:
+%
+% beware in mkiv we don't have the typeset- prefix
+%
+% \setbuffer[typeset-b]\endbuffer
+% \setbuffer[typeset-a]\endbuffer
+%
+% todo:
+%
+% \appendtoks \setbuffer[typeset-b]\endbuffer\to \everystarttext
+% \appendtoks \setbuffer[typeset-a]\endbuffer\to \everystarttext
-\setfalse\externalfigurelevel
-\settrue \externalfigureflush
+\newcount\c_grph_buffers_n
-\installcorenamespace{externalfigures}
+\let\m_grph_buffers_filename\empty
-\def\doplaceexternalfigure[#1][#2][#3][#4][#5]%
- {\doifsomething{#2}% catches \defineexternalfigure dummies
- {\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}}
+\unexpanded\def\typesetbuffer
+ {\dodoubleempty\grph_buffers_typeset}
-\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi
+\def\grph_buffers_typeset[#1][#2]% beware: this will mix up the mp graphics
+ {\ifsecondargument
+ \grph_buffers_typeset_indeed[#1][#2]%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\grph_buffers_typeset_indeed[\jobname][#1]}%
+ {\grph_buffers_typeset_indeed[#1][]}%
+ \else
+ \grph_buffers_typeset_indeed[\jobname][]
+ \fi\fi}
-\def\dodoplaceexternalfigure[#1][#2][#3][#4][#5]%
+\def\grph_buffers_typeset_indeed[#1][#2]% we could use the via files
{\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
+ \global\advance\c_grph_buffers_n\plusone
+ \edef\m_grph_buffers_filename{\jobname-buffer-\the\c_grph_buffers_n}%
+ \ctxcommand{runbuffer("\m_grph_buffers_filename.tmp","#1",true)}%
+ \externalfigure[\m_grph_buffers_filename.pdf][#2]%
\egroup}
-\def\externalfigurereplacement#1#2#3%
- {\normalexpanded{\localframed
- [\??ef]
- [\c!width=\figurewidth,
- \c!height=\figureheight,
- \c!background=\v!color,
- \c!backgroundcolor=missingfigurecolor,
- \c!frame=\@@efframe]}% we need to expand this in order to prevent a loop
- {\tt\tfxx \nohyphens
- name: \expanded{\verbatimstring{#1}}\\%
- file: \expanded{\verbatimstring{#2}}\\%
- state: \expanded{\verbatimstring{#3}}}}
-
-\definecolor[missingfigurecolor][s=.8]
-
-\def\externalfigureplaceholder#1#2#3%
- {\localframed
- [\??ef]
- [\c!width=#2,
- \c!height=#3,
- \c!frame=\v!on]%
- {\tt\tfxx \nohyphens
- name: \expanded{\verbatimstring{#1}}\\%
- state: \expanded{\verbatimstring{placeholder}}}}
-
-% new: more convenient/efficient than
-%
-% \use..[a][a][setting] \externalfigure[b][a]
-%
-% is equivalent to:
+% For manuals and such:
%
-% \def..[a][setting] \externalfigure[b][a]
-%
-% see x-res modules for usage:
+% \definetypesetting [name] [options] [settings-a]
%
-% \defineexternalfigure[name][settings]
-
-\unexpanded\def\defineexternalfigure
- {\dodoubleargument\dodefineexternalfigure}
-
-\def\dodefineexternalfigure[#1][#2]%
- {\setvalue{\??externalfigures#1}{\doplaceexternalfigure[#1][][][#2]}}
-
-% \useexternalfigure[alpha][koe]
-% \useexternalfigure[beta] [koe] [breedte=1cm]
-% \useexternalfigure[gamma][koe][alpha]
-% \useexternalfigure[delta][koe][alpha][breedte=2cm]
+% \typesetfile [name] [file] [settings-b]
+% \typesetfile [file] [options] [settings-b]
+% \typesetfile [file] [settings-b]
+% \typesetfile [file]
%
-% volle breedte: \externalfigure[koe] \par
-% 3cm breed: \externalfigure[koe] [breedte=3cm] \par
-% volle breedte: \externalfigure[alpha] \par
-% 1cm breed: \externalfigure[beta] \par
-% volle breedte: \externalfigure[gamma] \par
-% 2cm breed: \externalfigure[delta] \par
-% 4cm breed: \externalfigure[beta] [breedte=4cm] \par
-% 5cm breed: \externalfigure[gamma][breedte=5cm] \par
-
-% \defineexternalfigure[a][width=10cm]
-% \defineexternalfigure[b][width=5cm]
-% \externalfigure[cow][a]
-% \externalfigure[cow][b][height=8cm]
-
-% \useexternalfigure[x][cow][width=10cm,height=1cm]
-% \externalfigure[x]
-% \externalfigure[x][width=3cm]
-
-\def\useexternalfigure
- {\doquadrupleempty\douseexternalfigure}
-
-% [label] [filename]
-% [label] [filename] [parent]
-% [label] [filename] [parent] [settings]
-% [label] [filename] [settings]
-
-\def\useexternalfigure
- {\doquadrupleempty\douseexternalfigure}
-
-\def\douseexternalfigure[#1][#2][#3][#4]%
- {\doifelsenothing{#1}
- {\doifsomething{#2}
- {\doifassignmentelse{#3}
- {\dodouseexternalfigure{#2}{#2}{#3}{#4}}
- {\dodouseexternalfigure{#2}{#2}{}{#4}}}}
- {\doifelsenothing{#2}
- {\doifassignmentelse{#3}
- {\dodouseexternalfigure{#1}{#1}{}{#3}}
- {\dodouseexternalfigure{#1}{#1}{#3}{#4}}}
- {\doifassignmentelse{#3}
- {\dodouseexternalfigure{#1}{#2}{}{#3}}
- {\dodouseexternalfigure{#1}{#2}{#3}{#4}}}}}
-
-\def\dodouseexternalfigure#1#2#3#4%
- {\setvalue{\??externalfigures#1}{\doplaceexternalfigure[#1][#2][#3][#4]}%
- \doanalyzeexternalfigurecollection[#2][#4]}
-
-\newconditional\inexternalfigurecollection
-\newdimen\xexternalfigurecollectionminwidth
-\newdimen\xexternalfigurecollectionmaxwidth
-\newdimen\xexternalfigurecollectionminheight
-\newdimen\xexternalfigurecollectionmaxheight
-
-\def\doanalyzeexternalfigurecollection[#1][#2]%
- {\ifconditional\inexternalfigurecollection
- \setfalse\inexternalfigurecollection
- \getfiguredimensions[#1][#2]%
- \settrue\inexternalfigurecollection
- \scratchdimen\naturalfigurewidth
- \ifdim\scratchdimen>\xexternalfigurecollectionmaxwidth \xexternalfigurecollectionmaxwidth \scratchdimen \fi
- \ifdim\scratchdimen<\xexternalfigurecollectionminwidth \xexternalfigurecollectionminwidth \scratchdimen \fi
- \scratchdimen\naturalfigureheight
- \ifdim\scratchdimen>\xexternalfigurecollectionmaxheight \xexternalfigurecollectionmaxheight\scratchdimen \fi
- \ifdim\scratchdimen<\xexternalfigurecollectionminheight \xexternalfigurecollectionminheight\scratchdimen \fi
- \fi}
-
-\unexpanded\def\startexternalfigurecollection[#1]%
- {\begingroup
- \def\currentexternalfigurecollection{#1}%
- \settrue\inexternalfigurecollection
- \xexternalfigurecollectionminwidth \maxdimen
- \xexternalfigurecollectionmaxwidth \zeropoint
- \xexternalfigurecollectionminheight\maxdimen
- \xexternalfigurecollectionmaxheight\zeropoint}
-
-\unexpanded\def\stopexternalfigurecollection
- {\setxvalue{\??ef:c:\currentexternalfigurecollection:\c!minwidth }{\the\xexternalfigurecollectionminwidth }%
- \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!maxwidth }{\the\xexternalfigurecollectionmaxwidth }%
- \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!minheight}{\the\xexternalfigurecollectionminheight}%
- \setxvalue{\??ef:c:\currentexternalfigurecollection:\c!maxheight}{\the\xexternalfigurecollectionmaxheight}%
- \endgroup}
-
-\def\externalfigurecollectionparameter#1#2%
- {\csname\ifcsname\??ef:c:#1:#2\endcsname\??ef:c:#1:#2\else\s!empty\fi\endcsname}
-
-\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth }
-\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth }
-\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight}
-\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight}
-
-\let\efcparameter\externalfigurecollectionparameter
-\let\efcminwidth \externalfigurecollectionminwidth
-\let\efcmaxwidth \externalfigurecollectionmaxwidth
-\let\efcminheight\externalfigurecollectionminheight
-\let\efcmaxheight\externalfigurecollectionmaxheight
-
-% \startexternalfigurecollection[name]
-% \useexternalfigure[cow] [cow.pdf]
-% \useexternalfigure[mill][mill.png]
-% \stopexternalfigurecollection
+% \enabletrackers[files.run]
% \starttext
-% \bTABLE
-% \bTR
-% \bTD \externalfigure[cow] [height=\externalfigurecollectionmaxheight{name}] \eTD
-% \bTD \externalfigure[mill][height=\externalfigurecollectionmaxheight{name}] \eTD
-% \eTR
-% \eTABLE
+% \typesetfile[oepsoeps.tex][width=10cm,frame=on]
% \stoptext
-\def\dosetefparameters#1#2#3% parent_id use_settings current_settings
- {\doifelsenothing{#1} % inherit from parent
- {\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 % 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}
-
-\def\resourcecomment#1%
- {\gdef\currentresourcecomment{#1}}
+\installcorenamespace{typesettingfile}
-\unexpanded\def\startresourcecomment#1\stopresourcecomment
- {\gdef\currentresourcecomment{#1}}
+\unexpanded\def\definetypesetting{\dotripleempty\grph_typesetting_define}
+\unexpanded\def\typesetfile {\dotripleempty\grph_typesetting_process}
-\let\currentresourcecomment\empty
+\def\grph_typesetting_define[#1][#2][#3]% <name> options settings-a
+ {\doifsomething{#1}{\setuvalue{\??typesettingfile#1}{\grph_typesetting_process_indeed{#2}{#3}}}}
-\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\grph_typesetting_process[#1][#2][#3]% <name> filename settings-b | filename options settings
+ {\ifcsname\??typesettingfile#1\endcsname
+ \csname\??typesettingfile#1\endcsname{#2}{#3}%
+ \else\ifthirdargument % filename options settings
+ \grph_typesetting_process_indeed{#2}{#3}{#1}{}%
+ \else\ifsecondargument % filename settings
+ \grph_typesetting_process_indeed{}{#2}{#1}{}%
+ \fi\fi\fi}
-\unexpanded\def\overlayfigure#1%
- {\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]}
+\def\grph_typesetting_process_indeed#1#2#3#4% options settings-a filename settings-b
+ {\begingroup
+ \edef\m_typesetting_name{\cldcontext{job.files.context("#3","#1")}}%
+ \ifx\m_typesetting_name\empty \else
+ \expanded{\externalfigure[\m_typesetting_name]}[#2,#4]%
+ \fi
+ \endgroup}
-%D Whatever
+%D Whatever ... hardly used ... but historic ... needs checking ...
+%D will probably become m-fig-nn.mkiv .. or I will extend it cq. clean
+%D it up when I needed it. After all, it's documented in old manuals.
-\newbox\colorbarbox
+\newcount\c_grph_steps_reference
+\newdimen\d_grph_steps_x
+\newdimen\d_grph_steps_y
+\newbox \b_grph_steps_colorbar
-\unexpanded\def\makecolorbar[#1]%
- {\def\docommand##1%
- {\color[##1]
- {\blackrule
- [\c!width=2em,
- \c!height=1ex,
- \c!depth=\!!zeropoint]}%
- \endgraf}%
- \global\setbox\colorbarbox\vbox
- {\forgetall
- \processcommalist[#1]\docommand}%
- \global\setbox\colorbarbox\vbox
- {\hskip2em\box\colorbarbox}%
- \wd\colorbarbox\zeropoint}
+\let\placestopfigure\relax
\unexpanded\def\placestartfigure[#1][#2][#3]#4\placestopfigure[#5]%
{\hbox
- {\setbox0\hbox
+ {\setbox\scratchbox\hbox
{\useexternalfigure[\s!dummy][#2][#3,#5]%
\externalfigure[\s!dummy]}%
- \calculateefsteps
+ \grph_steps_calculate
\startpositioning
- \def\referring(##1,##2)##3(##4,##5)##6[##7]%
- {\position(##1,##2){\efgoto(##4,##5){\@@exframes}[##7]}}%
- \def\marking(##1,##2)##3(##4,##5)##6[##7]%
- {\position(##1,##2){\efthisis(##4,##5){\@@exframes}[##7]}}%
- \def\remark{\efnocomment}%
- \def\colorbar##1[##2]{}%
- \position(0,0){\box0}%
+ \let\referring\grph_steps_one_referring
+ \let\marking \grph_steps_one_marking
+ \let\remark \grph_steps_one_remark
+ \let\colorbar \grph_steps_one_colorbar
+ \position(0,0){\box\scratchbox}%
\linewidth\onepoint
\setuppositioning
[\c!unit=pt,
- \c!xscale=\withoutpt\the\efxsteps,
- \c!yscale=\withoutpt\the\efysteps,
+ \c!xscale=\withoutpt\the\d_grph_steps_x,
+ \c!yscale=\withoutpt\the\d_grph_steps_y,
\c!factor=1]%
\ignorespaces#4%
- \def\referring(##1,##2)##3(##4,##5)##6[##7]%
- {}%
- \let\marking\referring
- \def\remark{\efcomment\v!no}%
- \def\colorbar##1[##2]{\makecolorbar[##2]}%
+ \let\referring\grph_steps_two_referring
+ \let\marking \grph_steps_two_marking
+ \let\remark \grph_steps_two_remark
+ \let\colorbar \grph_steps_two_colorbar
\ignorespaces#4%
\stoppositioning
- \box\colorbarbox}}
+ \ifvoid\b_grph_steps_colorbar\else\box\b_grph_steps_colorbar\fi}} % not really needed
+
+\unexpanded\def\grph_steps_one_referring(#1,#2)#3(#4,#5)#6[#7]%
+ {\position(#1,#2){\grph_steps_goto(#4,#5){\externalfigureparameter\c!frames}[#7]}}
+
+\unexpanded\def\grph_steps_one_marking(#1,#2)#3(#4,#5)#6[#7]%
+ {\position(#1,#2){\grph_steps_this_is(#4,#5){\externalfigureparameter\c!frames}[#7]}}
+
+\unexpanded\def\grph_steps_one_remark(#1,#2)#3(#4,#5)% (x,y)(h,b)[...]{tekst}
+ {\def\grph_steps_no_comment_indeed[##1]##2{}%
+ \dosingleempty\grph_steps_no_comment_indeed}
+
+\unexpanded\def\grph_steps_one_colorbar#1[#2]%
+ {}
+
+\unexpanded\def\grph_steps_two_referring(#1,#2)#3(#4,#5)#6[#7]%
+ {}
+
+\let\grph_steps_two_marking\grph_steps_two_referring
+
+\unexpanded\def\grph_steps_two_remark
+ {\grph_steps_comment\v!no}
+
+\unexpanded\def\grph_steps_two_colorbar#1[#2]
+ {\begingroup
+ \global\setbox\b_grph_steps_colorbar\vbox
+ {\forgetall
+ \processcommalist[#2]\grph_colorbar_make_step}%
+ \global\setbox\b_grph_steps_colorbar\vbox
+ {\hskip2\emwidth\box\b_grph_steps_colorbar}%
+ \global\wd\b_grph_steps_colorbar\zeropoint
+ \endgroup}
-\def\dodostartfigure[#1][#2][#3]#4\stopfigure
- {\doifelse\v!test\@@exoption
+\unexpanded\def\grph_colorbar_make_step#1%
+ {\blackrule[\c!color=#1,\c!width=2\emwidth,\c!height=\exheight,\c!depth=\zeropoint]%
+ \endgraf}
+
+\unexpanded\def\startfigure % could be done nicer
+ {\grabuntil{\e!stop\v!figure}\grph_steps_figure_process}
+
+\let\stopfigure\relax
+
+\def\grph_steps_figure_process#1%
+ {\dotripleargument\grph_steps_figure_process_indeed#1\stopfigure}
+
+\def\grph_steps_figure_process_indeed[#1][#2][#3]#4\stopfigure
+ {\doifelse{\externalfigureparameter\c!option}\v!test
{\teststartfigure[#1][#2][#3]#4\teststopfigure
- \let\@@exframes\v!on}
- {\let\@@exframes\v!off}%
- \setvalue{\??externalfigures#1}%
- {\dosingleempty{\placestartfigure[#1][#2][#3]#4\placestopfigure}}%
- }% no longer \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}}
+ \letexternalfigureparameter\c!frames\v!on}
+ {\letexternalfigureparameter\c!frames\v!off}%
+ \setvalue{\??externalfigureinstance#1}%
+ {\dosingleempty{\placestartfigure[#1][#2][#3]#4\placestopfigure}}}
-% De onderstaande macro mag niet zondermeer worden aangepast
-% en is afgestemd op gebruik in de handleiding.
+\let\teststopfigure\relax
-\def\teststartfigure[#1][#2][#3]#4\teststopfigure%
+\unexpanded\def\teststartfigure[#1][#2][#3]#4\teststopfigure
{\begingroup
- \setbox0\hbox
+ \setbox\scratchbox\hbox
{\useexternalfigure[\s!dummy][#2][\c!wfactor=\v!max]%
\externalfigure[\s!dummy]}%
- \def\referring{\efmark}%
- \def\marking{\efmark}%
- \def\remark{\efcomment\v!yes}%
- \def\colorbar##1[##2]{}%
- \efreference\zerocount
+ \let\referring\grph_steps_three_referring
+ \let\marking \grph_steps_three_marking
+ \let\remark \grph_steps_three_remark
+ \let\colorbar \grph_steps_three_colorbar
+ \c_grph_steps_reference\zerocount
\setbox0\vbox
- {\hsize240pt
+ {\hsize240\points
\startpositioning
- \calculateefsteps
+ \grph_steps_calculate
\position(0,0)
- {\box0}%
+ {\box\scratchbox}%
\position(0,0)
{\basegrid
- [\c!nx=\@@exxmax,
- \c!dx=\withoutpt\the\efxsteps,
- \c!ny=\@@exymax,
- \c!dy=\withoutpt\the\efysteps,
+ [\c!nx=\externalfigureparameter\c!xmax,
+ \c!dx=\withoutpt\the\d_grph_steps_x,
+ \c!ny=\externalfigureparameter\c!ymax,
+ \c!dy=\withoutpt\the\d_grph_steps_y,
\c!xstep=1,
\c!ystep=1,
\c!scale=1,
@@ -363,18 +210,18 @@
\c!unit=pt]}%
\setuppositioning
[\c!unit=pt,
- \c!xscale=\withoutpt\the\efxsteps,
- \c!yscale=\withoutpt\the\efysteps,
+ \c!xscale=\withoutpt\the\d_grph_steps_x,
+ \c!yscale=\withoutpt\the\d_grph_steps_y,
\c!factor=1]%
\linewidth\onepoint
\ignorespaces#4\relax
\stoppositioning
\vfill}%
- \efreference\zerocount
- \def\referring{\eftext{$\rightarrow$}}%
- \def\marking{\eftext{$\leftarrow$}}%
- \def\remark{\efnocomment}%
- \def\colorbar##1[##2]{}%
+ \c_grph_steps_reference\zerocount
+ \let\referring\grph_steps_four_referring
+ \let\marking \grph_steps_four_marking
+ \let\remark \grph_steps_four_remark
+ \let\colorbar \grph_steps_four_colorbar
\setbox2\vbox
{{\tfa\doifelsenothing{#1}{#2}{#1}}
\blank
@@ -386,165 +233,149 @@
\ht0\ht2
\fi
\hbox
- {\hskip3em
- \vtop{\vskip12pt\box0\vskip6pt}%
- \vtop{\vskip12pt\box2\vskip6pt}}%
+ {\hskip3\emwidth
+ \vtop{\vskip12\points\box0\vskip6\points}%
+ \vtop{\vskip12\points\box2\vskip6\points}}%
\endgroup}
-\def\dodostartfigure[#1][#2][#3]#4\stopfigure
- {\doifelse\v!test\@@exoption
- {\teststartfigure[#1][#2][#3]#4\teststopfigure
- \let\@@exframe\v!on}
- {\let\@@exframe\v!off}%
- \setvalue{\??externalfigures#1}%
- {\def\next{\placestartfigure[#1][#2][#3]#4\placestopfigure}%
- \dosingleempty\next}%
- }% no longer: \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}}
+\unexpanded\def\grph_steps_three_referring(#1,#2)#3(#4,#5)#6[#7]%
+ {\advance\c_grph_steps_reference\plusone
+ \position(#1,#2)
+ {\hbox{\the\c_grph_steps_reference}}%
+ \position(#1,#2)
+ {\gotosomeinternal\s!vwb{#7}\realfolio
+ {\grph_steps_marker(#4,#5)\v!on{\thisissomeinternal\s!vwa{#7}}}}}
-\long\def\dostartfigure#1%
- {\dotripleargument\dodostartfigure#1\stopfigure}
+\unexpanded\def\grph_steps_three_remark
+ {\grph_steps_comment\v!yes}
-\unexpanded\def\startfigure
- {\grabuntil{\e!stop\v!figure}\dostartfigure}
-
-%D NEW: used in styledesign manual
+\let\grph_steps_three_marking \grph_steps_three_referring
+\let\grph_steps_three_colorbar\grph_steps_one_colorbar
-% beware in mkiv we don't have the typeset- prefix
-%
-% \setbuffer[typeset-b]\endbuffer
-% \setbuffer[typeset-a]\endbuffer
-%
-% todo:
-%
-% \appendtoks \setbuffer[typeset-b]\endbuffer\to \everystarttext
-% \appendtoks \setbuffer[typeset-a]\endbuffer\to \everystarttext
+\unexpanded\def\grph_steps_four_referring
+ {\grph_steps_text{$\rightarrow$}}
-\newcount\noftypesetbuffers
+\unexpanded\def\grph_steps_four_marking
+ {\grph_steps_text{$\leftarrow$}}
-\def\typesetbuffer
- {\dodoubleempty\dotypesetbuffer}
+\let\grph_steps_four_remark \grph_steps_one_remark
+\let\grph_steps_four_colorbar\grph_steps_one_colorbar
-\def\dotypesetbuffer[#1][#2]% beware: this will mix up the mp graphics
- {\ifsecondargument
- \dodotypesetbuffer[#1][#2]%
- \else\iffirstargument
- \doifassignmentelse{#1}
- {\dodotypesetbuffer[\jobname][#1]}%
- {\dodotypesetbuffer[#1][]}%
+% Helpers:
+
+\def\grph_steps_calculate
+ {\ifnum0\externalfigureparameter\c!xmax=\zerocount
+ \ifnum0\externalfigureparameter\c!ymax=\zerocount
+ \setexternalfigureparameter\c!ymax{24}%
+ \fi
+ \d_grph_steps_y\figureheight
+ \divide\d_grph_steps_y \externalfigureparameter\c!ymax
+ \d_grph_steps_x\d_grph_steps_y
+ \scratchdimen\figurewidth
+ \advance\scratchdimen\d_grph_steps_y
+ \divide \scratchdimen\d_grph_steps_y
+ \setexternalfigureparameter\c!xmax{\number\scratchdimen}%
\else
- \dodotypesetbuffer[\jobname][]
- \fi\fi}
+ \d_grph_steps_x\figurewidth \divide\d_grph_steps_x \externalfigureparameter\c!xmax\relax
+ \d_grph_steps_y\figureheight \divide\d_grph_steps_y \externalfigureparameter\c!ymax\relax
+ \fi}
-\def\dodotypesetbuffer[#1][#2]%
+\def\grph_steps_comment#1(#2,#3)#4(#5,#6)% {kader}(x,y)(h,b)[...]{tekst}
+ {\def\grph_steps_comment_indeed[##1]##2%
+ {\position(#2,#3)%
+ {\setnostrut
+ \framed
+ [\c!width=#5\d_grph_steps_x,
+ \c!height=#6\d_grph_steps_y,
+ \c!offset=\v!none,
+ \c!frame=#1,
+ ##1]%
+ {##2}}}%
+ \dosingleempty\grph_steps_comment_indeed}
+
+% \def\grph_steps_figure#1%
+% {\position(0,0){\getvalue{#1}}}
+
+\def\grph_steps_goto(#1,#2)#3[#4]% (h,b)kader[ref]
+ {\gotobox{\vbox{\grph_steps_area(#1,#2)#3{}}}[#4]}
+
+\def\grph_steps_text#1(#2,#3)#4(#5,#6)#7[#8]%
+ {\advance\c_grph_steps_reference\plusone
+ \hbox
+ {\quad
+ \thisissomeinternal\s!vwb
+ {#8}%
+ \gotosomeinternal\s!vwa{#8}\realfolio
+ {\hbox to 1.5em{\the\c_grph_steps_reference\presetgoto\hfill}}%
+ \quad#1 (#2,#3) (#5,#6) [#8]\hfill}%
+ \endgraf}
+
+\def\grph_steps_this_is(#1,#2)#3[#4]%
+ {\grph_steps_area(#1,#2){#3}{\pagereference[#4]}}
+
+\def\grph_steps_area(#1,#2)#3#4% (h,b){kader}{tekst}
{\bgroup
- \global\advance\noftypesetbuffers\plusone
- \edef\bufferfilename{\jobname-buffer-\the\noftypesetbuffers}%
- \ctxcommand{runbuffer("\bufferfilename.tmp","#1",true)}%
- \externalfigure[\bufferfilename.pdf][#2]%
+ \setnostrut
+ \framed
+ [\c!width=#1\d_grph_steps_x,
+ \c!height=#2\d_grph_steps_y,
+ \c!offset=\zeropoint,
+ \c!frame=#3]
+ {#4}%
\egroup}
-\def\dodotypesetbufferindeed#1%
- {}
+\def\grph_steps_marker(#1,#2)#3#4% (h,b){kader}{tekst}
+ {\framed
+ [\c!width=#1\d_grph_steps_x,
+ \c!height=#2\d_grph_steps_y,
+ \c!offset=\v!none,
+ \c!frame=#3]%
+ {#4}}
-% for me only (manuals and such)
+\protect \endinput
+
+% \startbuffer
+% \definecolor [blue] [c=1,m=.38,y=0,k=.64]
+% \definecolor [yellow] [c=0,m=.28,y=1,k=.06]
%
-% \definetypesetting [name] [options] [settings-a]
+% \definespotcolor [blue-100] [blue] [p=1]
+% \definespotcolor [yellow-100] [yellow] [p=1]
%
-% \typesetfile [name] [file] [settings-b]
-% \typesetfile [file] [options] [settings-b]
-% \typesetfile [file] [settings-b]
-% \typesetfile [file]
+% \definemultitonecolor [combicolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1]
%
-% \enabletrackers[files.run]
-% \starttext
-% \typesetfile[oepsoeps.tex][width=10cm,frame=on]
-% \stoptext
-
-\installcorenamespace{typesettingfile}
-
-\unexpanded\def\definetypesetting{\dotripleempty\dodefinetypesetting}
-\unexpanded\def\typesetfile {\dotripleempty\dotypesetfile}
-
-\def\dodefinetypesetting[#1][#2][#3]% <name> options settings-a
- {\doifsomething{#1}{\setvalue{\??typesettingfile#1}{\dodotypesetfile{#2}{#3}}}}
-
-\def\dotypesetfile[#1][#2][#3]% <name> filename settings-b | filename options settings
- {\ifcsname\??typesettingfile#1\endcsname
- \csname\??typesettingfile#1\endcsname{#2}{#3}%
- \else\ifthirdargument % filename options settings
- \dodotypesetfile{#2}{#3}{#1}{}%
- \else\ifsecondargument % filename settings
- \dodotypesetfile{}{#2}{#1}{}%
- \fi\fi\fi}
-
-\def\dodotypesetfile#1#2#3#4% options settings-a filename settings-b
- {\edef\typesetfilename{\ctxlua{tex.write(job.files.context("#3","#1"))}}%
- \expanded{\externalfigure[\typesetfilename]}[#2,#4]}
-
-\setupexternalfigures
- [\c!option=,
- \c!object=\v!yes, % we only check for no
- \c!reset=\v!no,
- \c!interaction=\v!none,
- \c!maxwidth=\@@efwidth,
- \c!maxheight=\@@efheight,
- \c!bodyfont=\bodyfontsize,
- \c!directory=,
- \c!radius=.5\bodyfontsize,
- \c!corner=\v!rectangular,
- \c!frame=\v!off,
- \c!background=, % new
- \c!splitcolor=\s!white,
- \c!conversion=,
- \c!resolution=,
- \c!prefix=,
- \c!cache=,
-% \c!grid=,
- \c!equalwidth=,
- \c!equalheight=,
- \c!location={\v!local,\v!global}]
-
-\setupexternalfigures
- [\c!frames=\v!off,
- \c!ymax=24,
- \c!xmax=]
-
-\useexternalfigure
- [buffer] [\jobname.buffer] [\c!object=\v!no]
-
-\protect \endinput
-
-% alternative for positioning
-
-% \definelayer[figure][width=\overlaywidth,height=\overlayheight]
-% \defineoverlay[figure][{\directsetup{figure}\tightlayer[figure]}]
-
-% \setupcolors[state=start]
-
-% \starttext
-
-% \startsetups figure
-% \setlayerframed[figure][preset=rightbottom,x=.25\layerwidth,y=.25\layerheight]{HERE}
-% \setlayerframed[figure][preset=leftbottom, x=.15\layerwidth,y=.35\layerheight]{THERE}
-% \stopsetups
-
-% \externalfigure[cow][background={foreground,figure},width=4cm,height=8cm]
-
-% \startsetups figure
-% \setlayerframed[figure][preset=righttop,x=.25\layerwidth,y=.25\layerheight]{MORE}
-% \setlayerframed[figure][preset=middle,foregroundcolor=green]{EVEN MORE}
-% \stopsetups
-
-% \externalfigure[cow][background={foreground,figure},width=14cm,height=2cm]
-
-% \defineexternalfigure[whatever][background={foreground,figure}]
-
-% \startsetups figure
-% \setlayerframed[figure][preset=righttop,x=.25\layerwidth,y=.25\layerheight]{\red MORE}
-% \setlayerframed[figure][preset=middle,foregroundcolor=green]{EVEN MORE}
-% \stopsetups
-
-% \externalfigure[cow][whatever][width=14cm,height=4cm]
-
-% \stoptext
-
+% \definemultitonecolor [combicolor-b] [blue=1] [c=1,m=.38,y=0,k=.64] % force multitone
+% \definemultitonecolor [combicolor-y] [yellow=1] [c=0,m=.28,y=1,k=.06] % force multitone
+%
+% \useexternalfigure[demo-a][mill.png] [object=no,width=.2\textwidth]
+% \useexternalfigure[demo-b][hacker-bw.jpg][object=no,width=.2\textwidth]
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-a]} {no color}
+% {\externalfigure[demo-a][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-a][color=combicolor-b]} {spot color}
+% {\externalfigure[demo-a][color=combicolor-y]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-b]} {no color}
+% {\externalfigure[demo-b][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-b][color=combicolor-b]} {spot color}
+% {\externalfigure[demo-b][color=combicolor-y]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-a]} {no color}
+% {\externalfigure[demo-a][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-a][color=blue-100]} {spot color}
+% {\externalfigure[demo-a][color=yellow-100]} {spot color}
+% \stopcombination \stopbaselinecorrection
+%
+% \startbaselinecorrection \startcombination[4*1]
+% {\externalfigure[demo-b]} {no color}
+% {\externalfigure[demo-b][color=combicolor]} {indexed duotone}
+% {\externalfigure[demo-b][color=blue-100]} {spot color}
+% {\externalfigure[demo-b][color=yellow-100]} {spot color}
+% \stopcombination \stopbaselinecorrection
+% \stopbuffer
+%
+% \getbuffer \typebuffer
diff --git a/tex/context/base/grph-fil.lua b/tex/context/base/grph-fil.lua
index 1ec88b487..9cdda13e0 100644
--- a/tex/context/base/grph-fil.lua
+++ b/tex/context/base/grph-fil.lua
@@ -6,13 +6,13 @@ if not modules then modules = { } end modules ['grph-fil'] = {
license = "see context related readme files"
}
-local format, concat = string.format, table.concat
-
-local trace_run = false trackers.register("graphic.runfile",function(v) trace_run = v end)
+local type = type
+local trace_run = false trackers.register("graphic.runfile",function(v) trace_run = v end)
local report_run = logs.reporter("graphics","run")
--- this code will move
+-- Historically running files is part of graphics processing, so this is why it
+-- sits here but is part of the job namespace.
local allocate = utilities.storage.allocate
@@ -22,6 +22,7 @@ local tobesaved = allocate()
local jobfiles = {
collected = collected,
tobesaved = tobesaved,
+ forcerun = false, -- maybe a directive some day
}
job.files = jobfiles
@@ -33,8 +34,6 @@ end
job.register('job.files.collected', tobesaved, initializer)
-jobfiles.forcerun = false
-
function jobfiles.run(name,action)
local oldchecksum = collected[name]
local newchecksum = file.checksum(name)
diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua
index 33dd0766d..f8c9a5134 100644
--- a/tex/context/base/grph-inc.lua
+++ b/tex/context/base/grph-inc.lua
@@ -15,6 +15,7 @@ if not modules then modules = { } end modules ['grph-inc'] = {
-- partly qualified
-- dimensions
-- consult rlx
+-- use metatables
-- figures.boxnumber can go as we now can use names
@@ -68,7 +69,7 @@ local report_inclusion = logs.reporter("graphics","inclusion")
local context, img = context, img
---- some extra img functions ---
+--- some extra img functions --- can become luat-img.lua
local imgkeys = img.keys()
@@ -154,16 +155,16 @@ figures.cachepaths = allocate {
figures.paths = allocate(table.copy(figures.localpaths))
-figures.order = allocate{
+local lookuporder = allocate {
"pdf", "mps", "jpg", "png", "jp2", "jbig", "svg", "eps", "tif", "gif", "mov", "buffer", "tex", "cld", "auto",
}
-local formats = allocate {
+local formats = allocate { -- magic and order will move here
["pdf"] = { list = { "pdf" } },
["mps"] = { patterns = { "mps", "%d+" } },
["jpg"] = { list = { "jpg", "jpeg" } },
- ["jp2"] = { list = { "jp2" } },
["png"] = { list = { "png" } },
+ ["jp2"] = { list = { "jp2" } },
["jbig"] = { list = { "jbig", "jbig2", "jb2" } },
["svg"] = { list = { "svg", "svgz" } },
["eps"] = { list = { "eps", "ai" } },
@@ -187,19 +188,44 @@ local magics = allocate {
figures.formats = formats -- frozen
figures.magics = magics -- frozen
+-- We can set the order but only indirectly so that we can check for support.
+
+function figures.setorder(list) -- can be table or string
+ if type(list) == "string" then
+ list = settings_to_array(list)
+ end
+ if list and #list > 0 then
+ lookuporder = allocate()
+ figures.order = lookuporder
+ local done = { } -- just to be sure in case the list is generated
+ for i=1,#list do
+ local l = lower(list[i])
+ if formats[l] and not done[l] then
+ lookuporder[#lookuporder+1] = l
+ done[l] = true
+ end
+ end
+ report_inclusion("lookup order: %s",concat(lookuporder," "))
+ else
+ -- invalid list
+ end
+end
+
function figures.guess(filename)
local f = io.open(filename,'rb')
if f then
local str = f:read(100)
f:close()
- for i=1,#magics do
- local pattern = magics[i]
- if pattern.pattern:match(str) then
- local format = pattern.format
- if trace_figures then
- report_inclusion("file %q has format %s",filename,format)
+ if str then
+ for i=1,#magics do
+ local pattern = magics[i]
+ if pattern.pattern:match(str) then
+ local format = pattern.format
+ if trace_figures then
+ report_inclusion("file %q has format %s",filename,format)
+ end
+ return format
end
- return format
end
end
end
@@ -208,7 +234,7 @@ end
function figures.setlookups() -- tobe redone .. just set locals
local fs, fp = allocate(), allocate()
figures.suffixes, figures.patterns = fs, fp
- for _, format in next, figures.order do
+ for _, format in next, lookuporder do
local data = formats[format]
local list = data.list
if list then
@@ -247,8 +273,8 @@ local function register(tag,target,what)
else
data[tag] = { what }
end
- if not contains(figures.order,target) then
- figures.order[#figures.order+1] = target
+ if not contains(lookuporder,target) then
+ lookuporder[#lookuporder+1] = target
end
figures.setlookups()
end
@@ -610,7 +636,7 @@ local function locate(request) -- name, format, cache
-- we could use the hashed data instead
local askedpath= file.is_rootbased_path(askedname)
local askedbase = file.basename(askedname)
- local askedformat = (request.format ~= "" and request.format ~= "unknown" and request.format) or file.extname(askedname) or ""
+ local askedformat = (request.format ~= "" and request.format ~= "unknown" and request.format) or file.suffix(askedname) or ""
local askedcache = request.cache
local askedconversion = request.conversion
local askedresolution = request.resolution
@@ -699,9 +725,8 @@ local function locate(request) -- name, format, cache
if trace_figures then
report_inclusion("strategy: rootbased path")
end
- local figureorder = figures.order
- for i=1,#figureorder do
- local format = figureorder[i]
+ for i=1,#lookuporder do
+ local format = lookuporder[i]
local list = formats[format].list or { format }
for j=1,#list do
local suffix = list[j]
@@ -725,9 +750,8 @@ local function locate(request) -- name, format, cache
report_inclusion("strategy: unknown format, prefer quality")
end
local figurepaths = figures.paths
- local figureorder = figures.order
- for j=1,#figureorder do
- local format = figureorder[j]
+ for j=1,#lookuporder do
+ local format = lookuporder[j]
local list = formats[format].list or { format }
for k=1,#list do
local suffix = list[k]
@@ -762,11 +786,10 @@ local function locate(request) -- name, format, cache
report_inclusion("strategy: unknown format, prefer path")
end
local figurepaths = figures.paths
- local figureorder = figures.order
for i=1,#figurepaths do
local path = figurepaths[i]
- for j=1,#figureorder do
- local format = figureorder[j]
+ for j=1,#lookuporder do
+ local format = lookuporder[j]
local list = formats[format].list or { format }
for k=1,#list do
local suffix = list[k]
@@ -790,9 +813,8 @@ local function locate(request) -- name, format, cache
if trace_figures then
report_inclusion("strategy: default tex path")
end
- local figureorder = figures.order
- for j=1,#figureorder do
- local format = figureorder[j]
+ for j=1,#lookuporder do
+ local format = lookuporder[j]
local list = formats[format].list or { format }
for k=1,#list do
local suffix = list[k]
@@ -1151,6 +1173,8 @@ local function makeoptions(options)
return (to == "table" and concat(options," ")) or (to == "string" and options) or ""
end
+-- programs.makeoptions = makeoptions
+
local function runprogram(template,binary,...)
local command = format(template,binary,...)
local binary = match(binary,"[%S]+") -- to be sure
@@ -1168,6 +1192,7 @@ end
local epsconverter = { }
converters.eps = epsconverter
+converters.ps = epsconverter
programs.gs = {
resolutions = {
@@ -1433,7 +1458,7 @@ function figures.applyratio(width,height,w,h) -- width and height are strings an
end
end
--- example of a simple plugin:
+-- example of simple plugins:
--
-- figures.converters.png = {
-- png = function(oldname,newname,resolution)
@@ -1443,9 +1468,18 @@ end
-- end,
-- }
+-- figures.converters.bmp = {
+-- pdf = function(oldname,newname)
+-- os.execute(string.format("gm convert %s %s",oldname,newname))
+-- end
+-- }
+
+-- local fig = figures.push { name = pdffile }
+-- figures.identify()
+-- figures.check()
+-- local nofpages = fig.used.pages
+-- figures.pop()
+
+-- interfacing
--- local fig = figures.push { name = pdffile }
--- figures.identify()
--- figures.check()
--- local nofpages = fig.used.pages
--- figures.pop()
+commands.setfigurelookuporder = figures.setorder
diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv
index 633130ea9..f96812d26 100644
--- a/tex/context/base/grph-inc.mkiv
+++ b/tex/context/base/grph-inc.mkiv
@@ -11,15 +11,9 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion}
-
-%D todo:
-%D
-%D - color conversion
-%D - alternative images
-%D - a few more obscure things
+% todo: messages
-% use framedcommandhandler
+\writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion}
\registerctxluafile{grph-inc}{1.001}
\registerctxluafile{grph-fil}{1.001}
@@ -28,25 +22,377 @@
\unprotect
-%D The following registers are used (if only to be downward compatible).
+%D Including graphics is complicated by the fact that we need to locate them first,
+%D optionally manipulate them and scale then next. Lookups are to be done as efficient
+%D as possible and inclusion of the data might happens only once. In \MKIV\ much of this
+%D is delegated to the \LUA\ end. There is nor so much less code as in \MKII\ but it's
+%D more powerful, flexible, pluggable and some of the extended functionality has been
+%D moved from modules to the core. The overall functionality is rather stable and has
+%D not changed much over the years.
+
+\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi
+
+\installcorenamespace{externalfigure}
+\installcorenamespace{externalfigureinstance}
+\installcorenamespace{externalfigurecollection}
+
+\installframedcommandhandler \??externalfigure {externalfigure} \??externalfigure
+
+\let\setupexternalfigures\setupexternalfigure
+
+\setupexternalfigures[% we really need the defaults
+ \c!method =,
+ \c!label =,
+ \c!size =,
+ \c!conversion =,
+ \c!resolution =,
+ \c!prefix =,
+ \c!cache =,
+ \c!page =\zerocount,
+ \c!display =,
+ \c!mask =,
+ \c!preset =\v!yes,
+ \c!split =,
+ \c!color =,
+ \c!symbol =\v!no,
+ \c!controls =\v!no,
+ \c!resources =,
+ \c!preview =\v!no
+ \c!repeat =\v!no
+ \c!foregroundcolor=,
+ \c!interaction =\v!none,
+ \c!hfactor =,
+ \c!wfactor =,
+ \c!factor =,
+ \c!maxwidth =\externalfigureparameter\c!width,
+ \c!maxheight =\externalfigureparameter\c!height,
+ \c!xscale =,
+ \c!yscale =,
+ \c!scale =,
+ \c!sx =\externalfigureparameter\c!s,
+ \c!sy =\externalfigureparameter\c!s,
+ \c!s =1,
+ \c!width =,
+ \c!height =,
+ \c!lines =,
+ \c!grid =,
+ \c!bodyfont =\bodyfontsize,
+ \c!object =\v!yes,
+ \c!corner =\v!rectangular,
+ \c!frame =\v!off,
+ \c!option =,
+ \c!reset =\v!no,
+ \c!directory =,
+ \c!radius =.5\bodyfontsize,
+ \c!background =,
+ \c!splitcolor =\s!white,
+ \c!order =,
+ \c!equalwidth =,
+ \c!equalheight =,
+ \c!location ={\v!local,\v!global},
+ \c!frames =\v!off,
+ \c!ymax =24,
+ \c!xmax =,
+ ]
+
+%D Defining figures.
+
+\newcount\c_grph_include_nesting
+
+\newtoks \everyexternalfigureresets % for the moment still public
+\newtoks \everyexternalfigurechecks % for the moment still public
+
+% \useexternalfigure[alpha][koe]
+% \useexternalfigure[beta] [koe] [breedte=1cm]
+% \useexternalfigure[gamma][koe][alpha]
+% \useexternalfigure[delta][koe][alpha][breedte=2cm]
+%
+% volle breedte: \externalfigure[koe] \par
+% 3cm breed: \externalfigure[koe] [breedte=3cm] \par
+% volle breedte: \externalfigure[alpha] \par
+% 1cm breed: \externalfigure[beta] \par
+% volle breedte: \externalfigure[gamma] \par
+% 2cm breed: \externalfigure[delta] \par
+% 4cm breed: \externalfigure[beta] [breedte=4cm] \par
+% 5cm breed: \externalfigure[gamma][breedte=5cm] \par
+%
+% \defineexternalfigure[a][width=10cm]
+% \defineexternalfigure[b][width=5cm]
+% \externalfigure[cow][a]
+% \externalfigure[cow][b][height=8cm]
+%
+% \useexternalfigure[x][cow][width=10cm,height=1cm]
+% \externalfigure[x]
+% \externalfigure[x][width=3cm]
+%
+% [label] [filename]
+% [label] [filename] [parent]
+% [label] [filename] [parent] [settings]
+% [label] [filename] [settings]
+%
+% new: more convenient/efficient than
+%
+% \use..[a][a][setting] \externalfigure[b][a]
+%
+% is equivalent to:
+%
+% \def..[a][setting] \externalfigure[b][a]
+%
+% see x-res modules for usage:
+%
+% \defineexternalfigure[name][settings]
+
+%D Defining is persistent, i.e.\ when you redefine an instance,
+%D the already set parameters need to be set again or otherwise
+%D the old values will be used.
+
+\newconditional\c_grph_include_trace_inheritance
+
+\installtextracker
+ {graphics.inheritance}
+ {\settrue \c_grph_include_trace_inheritance}
+ {\setfalse\c_grph_include_trace_inheritance}
+
+\installcorenamespace{externalfiguredefinition}
+
+% \unexpanded\def\defineexternalfigure
+% {\dodoubleargument\grph_include_define}
+%
+% \def\grph_include_define[#1][#2]%
+% {\setvalue{\??externalfiguredefinition#1}{\setupcurrentexternalfigure[#2]}}
+
+\let\defineexternalfigures\defineexternalfigure
+
+\unexpanded\def\useexternalfigure
+ {\doquadrupleempty\grph_include_use}
+
+% label file parent settings
+% label file settings
+% label file parent
+
+\def\grph_include_use[#1][#2][#3][#4]%
+ {\doifelsenothing{#1}
+ {\doifsomething{#2}
+ {\doifassignmentelse{#3}
+ {\grph_include_use_indeed{#2}{#2}{#3}{#4}}
+ {\grph_include_use_indeed{#2}{#2}\empty{#4}}}}
+ {\doifelsenothing{#2}
+ {\doifassignmentelse{#3}
+ {\grph_include_use_indeed{#1}{#1}\empty{#3}}
+ {\grph_include_use_indeed{#1}{#1}{#3}{#4}}}
+ {\doifassignmentelse{#3}
+ {\grph_include_use_indeed{#1}{#2}\empty{#3}}
+ {\grph_include_use_indeed{#1}{#2}{#3}{#4}}}}}
+
+\def\grph_include_use_indeed#1#2#3#4%
+ {\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}%
+ \grph_include_analyze_collection[#2][#4]}
+
+% inclusion
+
+\unexpanded\def\externalfigure
+ {\dotripleempty\grph_include_figure}
+
+\def\grph_include_figure[#1][#2][#3]%
+ {\docheckassignment{#2}%
+ \ifassignment
+ \grph_include_place[#1][][#2]%
+ \else
+ \grph_include_place[#1][#2][#3]%
+ \fi}
-\newbox \foundexternalfigure
-\newif \ifskipexternalfigures
-\newtoks \everyexternalfigureresets
-\newtoks \everyexternalfigurechecks
-\newtoks \externalfigurepostprocessors
+% todo: chain them
-\def\resetfigurevariables {\the\everyexternalfigureresets}
-\def\checkfigurevariables {\the\everyexternalfigurechecks}
+\def\grph_include_setup#1#2#3% name parent settings
+ {\edef\m_grph_include_name {#1}%
+ \edef\m_grph_include_parent{#2}%
+ \ifx\m_grph_include_name\empty \else
+ \let\p_grph_include_name\m_grph_include_name
+ \fi
+ \ifx\m_grph_include_parent\empty \else
+ \grph_include_inherit_from_parent\m_grph_include_parent
+ \fi
+ \setupcurrentexternalfigure[#3]}
+
+% \def\grph_include_inherit_from_parent#1%
+% {\ifcsname\??externalfiguredefinition#1\endcsname
+% \ifconditional\c_grph_include_trace_inheritance\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from definition: #1}\fi
+% \csname\??externalfiguredefinition#1\endcsname
+% \fi
+% \ifcsname\??externalfigureinstance#1\endcsname
+% \ifconditional\c_grph_include_trace_inheritance\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from instance: #1}\fi
+% \csname\??externalfigureinstance#1\endcsname
+% \fi}
-%D Historic feature:
+\def\grph_include_inherit_from_parent#1%
+ {%\ifcsname\??externalfiguredefinition#1\endcsname
+ % \ifconditional\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from definition: #1}\fi
+ % \csname\??externalfiguredefinition#1\endcsname
+ %\fi
+ \ifcsname\??externalfigure#1:\s!parent\endcsname
+ \let\currentexternalfigure#1%
+ \fi
+ \ifcsname\??externalfigureinstance#1\endcsname
+ \ifconditional\c_grph_include_trace_inheritance\writestatus\m!figures{inheriting from instance: #1}\fi
+ \csname\??externalfigureinstance#1\endcsname
+ \fi}
+
+\newtoks\t_grph_include_local_settings
\appendtoks
- \global\let\externalfigurelog\empty
-\to \everyexternalfigureresets
+ \let\textunderscore\letterunderscore % {\string _} % space needed as _ is now letter in unprotected mode (probably no longer needed)
+ %
+ \dontcomplain
+ \restorecatcodes
+ \forgetall
+\to \t_grph_include_local_settings
+
+\def\grph_include_place_inherit
+ {\ifconditional\c_grph_include_trace_inheritance
+ \writestatus\m!figures{label: \p_grph_include_label, name: \p_grph_include_name, parent: \p_grph_include_parent}%
+ \fi
+ \ifx\p_grph_include_parent\empty
+ % nothing to be done
+ \else\ifx\p_grph_include_parent\p_grph_include_label
+ % redundant
+ \else
+ \grph_include_inherit_from_parent\p_grph_include_parent
+ \fi\fi
+ \ifx\p_grph_include_label\empty
+ % nothing to be done
+ \else
+ \grph_include_inherit_from_parent\p_grph_include_label
+ \fi}
+
+\def\grph_include_place[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings]
+ {\bgroup
+ \advance\c_grph_include_nesting\plusone
+ \edef\currentexternalfigure{\the\c_grph_include_nesting}%
+ \checkexternalfigureparent % each inherits from the root
+ %
+ \the\everyexternalfigureresets
+ %
+ \edef\p_grph_include_label{#1}%
+ \let\p_grph_include_name\p_grph_include_label
+ \docheckassignment{#2}%
+ \ifassignment
+ % [label] [settings]
+ \let\p_grph_include_parent\p_grph_include_label
+ \grph_include_place_inherit
+ \setupcurrentexternalfigure[#2]%
+ \else
+ % [label] [parent] [settings]
+ \edef\p_grph_include_parent{#2}%
+ \ifx\p_grph_include_parent\empty
+ \let\p_grph_include_parent\p_grph_include_label
+ \fi
+ \grph_include_place_inherit
+ \setupcurrentexternalfigure[#3]%
+ \fi
+ %
+ \the\everyexternalfigurechecks
+ %
+ \the\t_grph_include_local_settings
+ \dostarttagged\t!image\empty
+ \ctxlua{figures.push {
+ name = "\p_grph_include_name",
+ label = "\p_grph_include_label",
+ page = "\externalfigureparameter\c!page",
+ size = "\externalfigureparameter\c!size",
+ object = "\externalfigureparameter\c!object",
+ prefix = "\externalfigureparameter\c!prefix",
+ cache = "\externalfigureparameter\c!cache",
+ format = "\externalfigureparameter\c!method",
+ preset = "\externalfigureparameter\c!prefix",
+ controls = "\externalfigureparameter\c!controls",
+ resources = "\externalfigureparameter\c!resources",
+ preview = "\externalfigureparameter\c!preview",
+ display = "\externalfigureparameter\c!display",
+ mask = "\externalfigureparameter\c!mask",
+ conversion = "\externalfigureparameter\c!conversion",
+ resolution = "\externalfigureparameter\c!resolution",
+ color = "\internalspotcolorparent{\externalfigureparameter\c!color}", % hack is needed
+ ["repeat"] = "\externalfigureparameter\c!repeat",
+ width = "\externalfigureparameter\c!width", % can be crap
+ height = "\externalfigureparameter\c!height", % can be crap
+ } }%
+ \ctxlua{figures.identify()}%
+ % also mode: checkpresense only
+ \ifconditional\c_grph_include_test_only
+ \ifcase\figurestatus \else
+ \ctxlua{figures.check()}%
+ \ctxlua{figures.dummy()}%
+ \ctxlua{figures.scale()}%
+ \ctxlua{figures.done()}%
+ \fi
+ \grph_include_set_mode
+ \else
+ \ifcase\figurestatus
+ \ctxlua{figures.dummy()}%
+ \ctxlua{figures.scale()}%
+ \else
+ \ctxlua{figures.check()}%
+ \ctxlua{figures.include()}%
+ \ctxlua{figures.scale()}%
+ \fi
+ \ctxlua{figures.done()}%
+ \grph_include_set_mode
+ \grph_include_finalize
+ \fi
+ \ctxlua{figures.pop()}%
+ \dotagfigure
+ \naturalvbox attr \imageattribute 2 {\box\foundexternalfigure}%
+ \dostoptagged
+ \egroup}
+
+%D Scaling:
+
+\let\dowithfigure\relax % name might change (into a proper hook)
-\let\runutilityfiletrue \relax \let\runutilityfilefalse \relax
-\let\consultutilityfiletrue\relax \let\consultutilityfilefalse\relax
+\unexpanded\def\doscalefigure % used at lua end
+ {\global\setbox\foundexternalfigure\vbox{\scale[\v!figure]{\dowithfigure{\box\foundexternalfigure}}}}
+
+\definescale % some day we will inherit
+ [\v!figure]
+ [\c!hfactor =\externalfigureparameter\c!hfactor,
+ \c!wfactor =\externalfigureparameter\c!wfactor,
+ \c!factor =\externalfigureparameter\c!factor,
+ \c!maxwidth =\externalfigureparameter\c!maxwidth ,
+ \c!maxheight =\externalfigureparameter\c!maxheight,
+ \c!equalwidth =\externalfigureparameter\c!equalwidth ,
+ \c!equalheight=\externalfigureparameter\c!equalheight,
+ \c!xscale =\externalfigureparameter\c!xscale,
+ \c!yscale =\externalfigureparameter\c!yscale,
+ \c!scale =\externalfigureparameter\c!scale,
+ \c!sx =\externalfigureparameter\c!sx,
+ \c!sy =\externalfigureparameter\c!sy,
+ \c!s =\externalfigureparameter\c!s,
+ \c!width =\externalfigureparameter\c!width,
+ \c!height =\externalfigureparameter\c!height,
+ \c!lines =\externalfigureparameter\c!lines]
+
+% % this will become:
+%
+% \unexpanded\def\doscalefigure % used at lua end
+% {\global\setbox\foundexternalfigure\vbox\bgroup
+% \bgroup
+% \let\currentscale\currentexternalfigure
+% \let\scaleparameter\externalfigureparameter
+% \dowithnextboxcs\grph_scale_finish\hbox{\dowithfigure{\box\foundexternalfigure}}%
+% \egroup}
+%
+% % or even better:
+%
+% \def\grph_scale_inherited#1%
+% {\bgroup
+% \expandafter\let\expandafter\currentscale \csname current#1\endcsname
+% \expandafter\let\expandafter\scaleparameter\csname #1parameter\endcsname
+% \dowithnextboxcs\grph_scale_finish\hbox}
+%
+% \unexpanded\def\doscalefigure % used at lua end
+% {\global\setbox\foundexternalfigure\vbox\bgroup
+% \grph_scale_inherited{externalfigure}{\dowithfigure{\box\foundexternalfigure}}%
+% \egroup}
%D You can register additional suffixes with the following command:
%D
@@ -57,19 +403,22 @@
%D \stoptyping
\unexpanded\def\definegraphictypesynonym
- {\dodoubleargument\dodefinegraphictypesynonym}
+ {\dodoubleargument\grph_include_set_type_synonym}
-\def\dodefinegraphictypesynonym[#1][#2]%
+\def\grph_include_set_type_synonym[#1][#2]%
{\ctxlua{figures.registersuffix("#1","#2")}}
%D Additional paths can be installed with the regular setup command. The next
%D macro picks up the list.
-\def\setfigurepathlist
- {\ctxlua{figures.setpaths("\@@exlocation",\!!bs\@@exdirectory\!!es)}}
+\unexpanded\def\setfigurepathlist
+ {\ctxlua{figures.setpaths("\externalfigureparameter\c!location",\!!bs\externalfigureparameter\c!directory\!!es)}}
%D Variables:
+\newbox \foundexternalfigure
+\newtoks\externalfigurepostprocessors
+
\def\defaultfigurewidth {8\lineheight}
\def\defaultfigureheight {6\lineheight}
@@ -112,209 +461,84 @@
\let\figurescalexscale \figurexscale
\let\figurescaleyscale \figureyscale
+%D Abuse:
+%D
+%D \starttyping
+%D \externalfigure[rubish.pdf] \ifcase\figurestatus\relax \ctxlua{os.exit(999)} \fi
+%D \stoptyping
+
+%D Calculating:
+
+% \enabletrackers[figures.conversion]
+% \externalfigure[demo.svg]
+% \externalfigure[demo.svg][conversion=png]
+
+%D The following registers are used (if only to be downward compatible).
+
+\newconditional\c_grph_include_skip
+\newconditional\c_grph_include_test_only
+\newconditional\c_grph_include_level \setfalse\c_grph_include_level % true=background false=normal
+\newconditional\c_grph_include_flush \settrue \c_grph_include_flush % true=place false=ignore
+
+\newsystemmode\v!figure
+
+\def\grph_include_set_mode
+ {\ifcase\figurestatus
+ \global\resetsystemmode\v!figure % todo, also: \v!resource
+ \else
+ \global\setsystemmode \v!figure % todo, also: \v!resource
+ \fi}
+
\appendtoks
- \ctxlua { % figures.defaultwidth .. why not dimen
- figures.setpaths("\@@exlocation","\@@exdirectory") ;
+ \ctxlua { % figures.defaultwidth .. maybe a dimen some day
+ figures.setpaths("\externalfigureparameter\c!location","\externalfigureparameter\c!directory") ;
figures.defaultwidth = \number\dimexpr\defaultfigurewidth \relax ;
figures.defaultheight = \number\dimexpr\defaultfigureheight\relax ;
figures.boxnumber = \number\foundexternalfigure ;
}%
\to \everyexternalfigureresets
-%D In some situations we need to make sure that the figure related variables
-%D are reset. This is especially important when we are nesting. Is this still
-%D needed in \MKIV.
-
-\def\resetexternalfigures
- {\let\@@efoption \empty % \let\@@efprefix\empty
- \let\@@efmaxwidth \empty % \let\@@efcache \empty
- \let\@@efmaxheight \empty % \let\@@efframe \v!off
- \let\@@efforegroundcolor\empty
- \let\@@efcolor \empty
- \let\@@efconversion \empty
- \let\@@efbackground \empty
- \let\@@efresolution \empty}
-
-\appendtoks \resetexternalfigures \to \everyoverlay
-\appendtoks \resetexternalfigures \to \everybeforepagebody % not really needed
-
-\def\resetfigureusersettings % if we use a command handler we can simply define a new instance
- {%
- \let\@@efmethod \empty
- \let\@@eflabel \empty
- \let\@@efsize \empty
- \let\@@efconversion\@@exconversion
- \let\@@efresolution\@@exresolution
- \let\@@efprefix \@@exprefix
- \let\@@efcache \@@excache
- \let\@@efpage \!!zerocount
- \let\@@efobject \@@exobject
- \let\@@efdisplay \empty
- \let\@@efmask \empty
- %
- \let\@@efpreset \v!yes
- \let\@@efsplit \empty
- \let\@@efcolor \empty
- %
- \let\@@efsymbol \v!no
- %
- \let\@@efcontrols \v!no
- \let\@@efresources \empty
- \let\@@efpreview \v!no
- \let\@@efrepeat \v!no
- %
- \let\@@efforegroundcolor\empty
- %
- \let\@@efinteraction\@@exinteraction
- %
- \let\@@efhfactor \empty
- \let\@@efwfactor \empty
- \let\@@effactor \empty
- \let\@@efmaxwidth \@@exmaxwidth
- \let\@@efmaxheight \@@exmaxheight
- \let\@@efxscale \empty
- \let\@@efyscale \empty
- \let\@@efscale \empty
- \let\@@efsx \!!plusone
- \let\@@efsy \!!plusone
- \let\@@efwidth \empty
- \let\@@efheight \empty
- \let\@@eflines \empty
- \let\@@efgrid \empty}
-
-\resetfigureusersettings
-
-\appendtoks
- \resetfigureusersettings
-\to \everyexternalfigureresets
-
-\def\checkfigureusersettings
- {% old features
- \doif\@@exoption\v!frame
- {\let\@@efframe\v!on}%
- \doif\@@exoption\v!empty
- {\skipexternalfigurestrue
- \let\@@efframe\v!off}%
- \doifsomething\@@efwidth {\doifdimensionelse\@@efwidth {\edef\@@efwidth {\the\dimexpr\@@efwidth }}\donothing}%
- \doifsomething\@@efheight{\doifdimensionelse\@@efheight{\edef\@@efheight{\the\dimexpr\@@efheight}}\donothing}%
- % fake color in gray bitmaps, assumes that
- % a transparent color is used
- \doifsomething\@@efforegroundcolor
- {\def\@@efbackground{\v!foreground,\v!color}%
- \def\@@efbackgroundcolor{\@@efforegroundcolor}}}
-
\appendtoks
- \checkfigureusersettings
+ \edef\p_option{\externalfigureparameter\c!option}%
+ \ifx\p_option\v!frame
+ \setfalse\c_grph_include_skip
+ \letexternalfigureparameter\c!frame\v!on
+ \else\ifx\p_option\v!empty
+ \settrue\c_grph_include_skip
+ \letexternalfigureparameter\c!frame\v!off
+ \else
+ \setfalse\c_grph_include_skip
+ \fi\fi
+ % fake color in gray bitmaps, assumes that
+ % a transparent color is used
+ \edef\p_foregroundcolor{\externalfigureparameter\c!foregroundcolor}%
+ \ifx\p_foregroundcolor\empty \else
+ \setexternalfigureparameter\c!background{\v!foreground,\v!color}%
+ \letexternalfigureparameter\c!backgroundcolor\p_foregroundcolor
+ \fi
\to \everyexternalfigurechecks
%D Internal graphics are handled at the \TEX\ end:
-\def\doprocesstexlikefigure#1% retrofit into mkii
+\def\grph_include_process_tex#1%
{\global\setbox\foundexternalfigure\vbox\framed
[\c!strut=\v!no,\c!align=\v!normal,\c!frame=\v!off,
\c!offset=\v!overlay,\c!width=\v!fit,\c!height=\v!fit]
{\blank[\v!disable]#1\endgraf\removelastskip}} % disable should stay here!
-\def\doprocessmpslikefigure#1% retrofit into mkii
+\def\grph_include_process_mps#1% retrofit into mkii
{\global\setbox\foundexternalfigure\vbox{\convertMPtoPDF{#1}11}}
-\def\doprocesscldlikefigure#1%
+\def\grph_include_process_cld#1%
{\global\setbox\foundexternalfigure\vbox{\cldprocessfile{#1}}}
-\def\docheckfigurebuffer #1{\doprocesstexlikefigure{\getbuffer[#1]}}
-\def\docheckfiguretex #1{\doprocesstexlikefigure{\input{#1}}}
-\def\docheckfigurecld #1{\doprocesscldlikefigure{#1}} % we can always add cldrun
-\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{\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
-
-% \enabletrackers[figures.conversion]
-% \externalfigure[demo.svg]
-% \externalfigure[demo.svg][conversion=png]
-
-\unexpanded\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current
- {\dontcomplain
- \restorecatcodes
- \forgetall
- \resetfigurevariables
- \dosetefparameters{#4}{#5}{#6}%
- \checkfigurevariables
-% \begingroup
-% \color[\@@efcolor]{\xdef\globcolorattr{\internalspotcolorname}}
-% \endgroup
- \ctxlua{figures.push {
- name = "#3",
- label = "#2", % todo: \@eflabel
- page = "\@@efpage",
- size = "\@@efsize",
- object = "\@@efobject",
- prefix = "\@@efprefix",
- cache = "\@@efcache",
- format = "\@@efmethod",
- preset = "\@@efprefix",
- controls = "\@@efcontrols",
- resources = "\@@efresources",
- preview = "\@@efpreview",
- display = "\@@efdisplay",
- mask = "\@@efmask",
- conversion = "\@@efconversion",
- resolution = "\@@efresolution",
- color = "\internalspotcolorparent\@@efcolor", % hack is needed
- ["repeat"] = "\@@efrepeat",
- width = "\@@efwidth", % can be crap
- height = "\@@efheight", % can be crap
- } }%
- \ctxlua{figures.identify()}%
- % also mode: checkpresense only
- \ifconditional\testexternalfigureonly
- \ifcase\figurestatus \else
- \ctxlua{figures.check()}%
- \ctxlua{figures.dummy()}%
- \ctxlua{figures.scale()}%
- \ctxlua{figures.done()}%
- \fi
- \signalexternalfigure
- \else
- \ifcase\figurestatus
- \ctxlua{figures.dummy()}%
- \ctxlua{figures.scale()}%
- \else
- \ctxlua{figures.check()}%
- \ctxlua{figures.include()}%
- \ctxlua{figures.scale()}%
- \fi
- \ctxlua{figures.done()}%
- \signalexternalfigure
- \finishexternalfigure
- \fi
- \ctxlua{figures.pop()}}
+\unexpanded\def\docheckfigurebuffer #1{\grph_include_process_tex{\getbuffer[#1]}} % used al lua end
+\unexpanded\def\docheckfiguretex #1{\grph_include_process_tex{\input{#1}}} % used al lua end
+\unexpanded\def\docheckfigurecld #1{\grph_include_process_cld{#1}} % used al lua end
+\unexpanded\def\docheckfiguremps #1{\grph_include_process_mps{#1}} % used al lua end
+\unexpanded\def\docheckfiguremprun #1#2{\grph_include_process_tex{\useMPrun{#1}{#2}}} % used al lua end
-\def\relocateexternalfigure % easier here than in lua
+\unexpanded\def\relocateexternalfigure % easier here than in lua
{\global\setbox\foundexternalfigure\vbox to \ht\foundexternalfigure\bgroup
\vss
\ht\foundexternalfigure\zeropoint
@@ -324,33 +548,24 @@
\egroup
\egroup}
-\newsystemmode\v!figure
-
-\def\signalexternalfigure % global (dup call to status)
- {\ifcase\figurestatus
- \global\resetsystemmode\v!figure % todo, also: \v!resource
- \else
- \global\setsystemmode \v!figure % todo, also: \v!resource
- \fi}
-
\unexpanded\def\startfoundexternalfigure#1#2% ht wd
{\global\setbox\foundexternalfigure\vbox to #2\bgroup\vss\hbox to #1\bgroup}
\unexpanded\def\stopfoundexternalfigure
{\hss\egroup\egroup}
-\def\emptyfoundexternalfigure
+\unexpanded\def\emptyfoundexternalfigure % sort of obsolete
{\startfoundexternalfigure\defaultfigurewidth\defaultfigureheight
\stopfoundexternalfigure}
-\def\finishexternalfigure % here we use \figurevariables
+\def\grph_include_finalize
{\global\setbox\foundexternalfigure\vbox
{\ifcase\figurestatus
- \let\@@efframe\v!on
+ \letexternalfigureparameter\c!frame\v!on
\fi
- \ifconditional\externalfigureflush
- \ifconditional\externalfigurelevel % probably background
- \ifskipexternalfigures
+ \ifconditional\c_grph_include_flush
+ \ifconditional\c_grph_include_level % probably background
+ \ifconditional\c_grph_include_skip
% nothing
\fakebox\foundexternalfigure
\else\ifcase\figurestatus
@@ -361,28 +576,29 @@
\fi\fi
\else
\iftrialtypesetting \else \feedbackexternalfigure \fi
- \settrue\externalfigurelevel
- \ifskipexternalfigures
+ \settrue\c_grph_include_level
+ \ifconditional\c_grph_include_skip
\ifcase\figurestatus
- \externalfigurereplacement\figurelabel\figurefileoriginal{unknown}%
+ \grph_include_replacement\figurelabel\figurefileoriginal{unknown}%
\else
- \externalfigurereplacement\figurelabel\figurefullname{skipped}%
+ \grph_include_replacement\figurelabel\figurefullname{skipped}%
\fi
\else\ifcase\figurestatus
- \externalfigurereplacement\figurelabel\figurefileoriginal{unknown}%
+ \grph_include_replacement\figurelabel\figurefileoriginal{unknown}%
\else
\the\externalfigurepostprocessors
- \doifelse\@@efreset\v!yes
- {\wd\foundexternalfigure\figurewidth
- \ht\foundexternalfigure\figureheight
- \dp\foundexternalfigure\zeropoint
- \box\foundexternalfigure}
- {\localframed % should also be applied to high res !
- [\??ef]
- [\c!offset=\v!overlay,
- \c!width=\figurewidth,
- \c!height=\figureheight]
- {\vfilll\box\foundexternalfigure}}%
+ \edef\p_reset{\externalfigureparameter\c!reset}%
+ \ifx\p_reset\v!yes
+ \wd\foundexternalfigure\figurewidth
+ \ht\foundexternalfigure\figureheight
+ \dp\foundexternalfigure\zeropoint
+ \box\foundexternalfigure
+ \else
+ \letexternalfigureparameter\c!offset\v!overlay
+ \letexternalfigureparameter\c!width \figurewidth
+ \letexternalfigureparameter\c!height\figureheight
+ \inheritedexternalfigureframed{\vfilll\box\foundexternalfigure}%
+ \fi
\fi\fi
\fi
\else
@@ -390,35 +606,17 @@
\iftrialtypesetting \else \feedbackexternalfigure \fi
\fi}}
-\ifx\externalfigurereplacement\undefined\let\externalfigurereplacement\gobblethreearguments\fi
-\ifx\externalfigureplaceholder\undefined\let\externalfigureplaceholder\gobblethreearguments\fi
+\let\feedbackexternalfigure\relax % hook
-\let\feedbackexternalfigure\relax % \gobblefourarguments
-\let\dowithfigure \relax
+\unexpanded\def\getfiguredimensions
+ {\dodoubleempty\grph_include_get_dimensions}
-\def\getfiguredimensions
- {\dodoubleempty\dogetfiguredimensions}
-
-\def\dogetfiguredimensions[#1][#2]%
+\def\grph_include_get_dimensions[#1][#2]%
{\startnointerference
- \settrue\testexternalfigureonly
+ \settrue\c_grph_include_test_only
\externalfigure[#1][#2,\c!display=,\c!mask=,\c!object=\v!no]%
\stopnointerference}
-\let\getfiguredimensionsonly\getfiguredimensions
-
-% \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 !
\ifcase\figurestatus
@@ -427,74 +625,137 @@
\expandafter\firstoftwoarguments
\fi}
-\def\registerexternalfigure % no placement, handy for preprocessing
- {\dotripleempty\doregisterexternalfigure}
+% No placement, handy for preprocessing:
-\def\doregisterexternalfigure[#1][#2][#3]%
+\unexpanded\def\registerexternalfigure
+ {\dotripleempty\grph_include_register}
+
+\def\grph_include_register[#1][#2][#3]%
{\startnointerference
- \testexternalfigureonly
- \setfalse\externalfigureflush % == test ?
- \externalfigure[#1][#2][#3]% or \doexternalfigure
+ \c_grph_include_test_only
+ \setfalse\c_grph_include_flush % == test ?
+ \externalfigure[#1][#2][#3]% or
\externalfigure[#1][#2,\c!display=,\c!mask=,\c!object=\v!no]%
\stopnointerference}
-% helpers (will be replaced when xforms are accessible at the lua end)
+% Helpers (will be replaced when xforms are accessible at the lua end)
-\def\dosetfigureobject#1%
+\unexpanded\def\dosetfigureobject#1%
{\setobject{FIG}{#1}\vbox{\box\foundexternalfigure}}
-\def\doboxfigureobject#1%
+\unexpanded\def\doboxfigureobject#1%
{\global\setbox\foundexternalfigure\vbox{\getobject{FIG}{#1}}} % probably one vbox too many
-% figurebases
+% Figure bases
-\def\usefigurebase[#1]%
+\unexpanded\def\usefigurebase[#1]%
{\ctxlua{figures.bases.use("#1")}}
-\protect \endinput
+\appendtoks
+ \setfigurepathlist % the path may be used elsewhere too (as in x-res-04)
+\to \everysetupexternalfigure
-% \startbuffer
-% \definecolor [blue] [c=1,m=.38,y=0,k=.64]
-% \definecolor [yellow] [c=0,m=.28,y=1,k=.06]
-%
-% \definespotcolor [blue-100] [blue] [p=1]
-% \definespotcolor [yellow-100] [yellow] [p=1]
-%
-% \definemultitonecolor [combicolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1]
-%
-% \definemultitonecolor [combicolor-b] [blue=1] [c=1,m=.38,y=0,k=.64] % force multitone
-% \definemultitonecolor [combicolor-y] [yellow=1] [c=0,m=.28,y=1,k=.06] % force multitone
-%
-% \useexternalfigure[demo-a][mill.png] [object=no,width=.2\textwidth]
-% \useexternalfigure[demo-b][hacker-bw.jpg][object=no,width=.2\textwidth]
-%
-% \startbaselinecorrection \startcombination[4*1]
-% {\externalfigure[demo-a]} {no color}
-% {\externalfigure[demo-a][color=combicolor]} {indexed duotone}
-% {\externalfigure[demo-a][color=combicolor-b]} {spot color}
-% {\externalfigure[demo-a][color=combicolor-y]} {spot color}
-% \stopcombination \stopbaselinecorrection
-%
-% \startbaselinecorrection \startcombination[4*1]
-% {\externalfigure[demo-b]} {no color}
-% {\externalfigure[demo-b][color=combicolor]} {indexed duotone}
-% {\externalfigure[demo-b][color=combicolor-b]} {spot color}
-% {\externalfigure[demo-b][color=combicolor-y]} {spot color}
-% \stopcombination \stopbaselinecorrection
-%
-% \startbaselinecorrection \startcombination[4*1]
-% {\externalfigure[demo-a]} {no color}
-% {\externalfigure[demo-a][color=combicolor]} {indexed duotone}
-% {\externalfigure[demo-a][color=blue-100]} {spot color}
-% {\externalfigure[demo-a][color=yellow-100]} {spot color}
-% \stopcombination \stopbaselinecorrection
-%
-% \startbaselinecorrection \startcombination[4*1]
-% {\externalfigure[demo-b]} {no color}
-% {\externalfigure[demo-b][color=combicolor]} {indexed duotone}
-% {\externalfigure[demo-b][color=blue-100]} {spot color}
-% {\externalfigure[demo-b][color=yellow-100]} {spot color}
-% \stopcombination \stopbaselinecorrection
-% \stopbuffer
-%
-% \getbuffer \typebuffer
+\appendtoks
+ \ctxcommand{setfigurelookuporder("\externalfigureparameter\c!order")}%
+\to \everysetupexternalfigure
+
+\definecolor[missingfigurecolor][s=.8]
+
+\def\grph_include_replacement#1#2#3%
+ {\bgroup
+ \letexternalfigureparameter\c!width\figurewidth
+ \letexternalfigureparameter\c!height\figureheight
+ \letexternalfigureparameter\c!background\v!color
+ \setexternalfigureparameter\c!backgroundcolor{missingfigurecolor}%
+ \inheritedexternalfigureframed
+ {\tt\tfxx \nohyphens
+ name: \expanded{\verbatimstring{#1}}\\%
+ file: \expanded{\verbatimstring{#2}}\\%
+ state: \expanded{\verbatimstring{#3}}}%
+ \egroup}
+
+% maybe setuphandler
+
+\newconditional\c_grph_include_in_collection
+
+\newdimen\d_grph_include_collection_minwidth
+\newdimen\d_grph_include_collection_maxwidth
+\newdimen\d_grph_include_collection_minheight
+\newdimen\d_grph_include_collection_maxheight
+
+\def\grph_include_analyze_collection[#1][#2]%
+ {\ifconditional\c_grph_include_in_collection
+ \setfalse\c_grph_include_in_collection
+ \getfiguredimensions[#1][#2]%
+ \settrue\c_grph_include_in_collection
+ \scratchdimen\naturalfigurewidth
+ \ifdim\scratchdimen>\d_grph_include_collection_maxwidth \d_grph_include_collection_maxwidth \scratchdimen \fi
+ \ifdim\scratchdimen<\d_grph_include_collection_minwidth \d_grph_include_collection_minwidth \scratchdimen \fi
+ \scratchdimen\naturalfigureheight
+ \ifdim\scratchdimen>\d_grph_include_collection_maxheight \d_grph_include_collection_maxheight\scratchdimen \fi
+ \ifdim\scratchdimen<\d_grph_include_collection_minheight \d_grph_include_collection_minheight\scratchdimen \fi
+ \fi}
+
+\unexpanded\def\startexternalfigurecollection[#1]%
+ {\begingroup
+ \def\currentexternalfigurecollection{#1}%
+ \settrue\c_grph_include_in_collection
+ \d_grph_include_collection_minwidth \maxdimen
+ \d_grph_include_collection_maxwidth \zeropoint
+ \d_grph_include_collection_minheight\maxdimen
+ \d_grph_include_collection_maxheight\zeropoint}
+
+\unexpanded\def\stopexternalfigurecollection
+ {\setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!minwidth }{\the\d_grph_include_collection_minwidth }%
+ \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!maxwidth }{\the\d_grph_include_collection_maxwidth }%
+ \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!minheight}{\the\d_grph_include_collection_minheight}%
+ \setxvalue{\??externalfigurecollection\currentexternalfigurecollection:\c!maxheight}{\the\d_grph_include_collection_maxheight}%
+ \endgroup}
+
+\def\externalfigurecollectionparameter#1#2%
+ {\csname
+ \ifcsname\??externalfigurecollection#1:#2\endcsname
+ \??externalfigurecollection#1:#2%
+ \else
+ \s!empty
+ \fi
+ \endcsname}
+
+\def\externalfigurecollectionminwidth #1{\externalfigurecollectionparameter{#1}\c!minwidth }
+\def\externalfigurecollectionmaxwidth #1{\externalfigurecollectionparameter{#1}\c!maxwidth }
+\def\externalfigurecollectionminheight#1{\externalfigurecollectionparameter{#1}\c!minheight}
+\def\externalfigurecollectionmaxheight#1{\externalfigurecollectionparameter{#1}\c!maxheight}
+
+\let\efcparameter\externalfigurecollectionparameter % still needed ?
+\let\efcminwidth \externalfigurecollectionminwidth % still needed ?
+\let\efcmaxwidth \externalfigurecollectionmaxwidth % still needed ?
+\let\efcminheight\externalfigurecollectionminheight % still needed ?
+\let\efcmaxheight\externalfigurecollectionmaxheight % still needed ?
+
+% \startexternalfigurecollection[name]
+% \useexternalfigure[cow] [cow.pdf]
+% \useexternalfigure[mill][mill.png]
+% \stopexternalfigurecollection
+% \starttext
+% \bTABLE
+% \bTR
+% \bTD \externalfigure[cow] [height=\externalfigurecollectionmaxheight{name}] \eTD
+% \bTD \externalfigure[mill][height=\externalfigurecollectionmaxheight{name}] \eTD
+% \eTR
+% \eTABLE
+% \stoptext
+
+\unexpanded\def\showexternalfigures
+ {\writestatus\m!system{the \string\showexternalfigures\space command is not (yet) implemented in mkiv}}
+
+\unexpanded\def\overlayfigure#1%
+ {\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]}
+
+% Bonus:
+
+\useexternalfigure
+ [buffer]
+ [\jobname.buffer]
+ [\c!object=\v!no]
+
+\protect \endinput
diff --git a/tex/context/base/grph-raw.lua b/tex/context/base/grph-raw.lua
index 361f6944d..4c5b031ea 100644
--- a/tex/context/base/grph-raw.lua
+++ b/tex/context/base/grph-raw.lua
@@ -10,9 +10,12 @@ if not modules then modules = { } end modules ['grph-raw'] = {
-- her gnuplot project. It's somewhat premliminary code but it
-- works ok for that purpose.
+local tonumber = tonumber
+
local report_bitmap = logs.reporter("graphics","bitmaps")
-local texsp = tex.sp
+local context = context
+local texsp = tex.sp
function figures.bitmapimage(t)
local data = t.data
diff --git a/tex/context/base/grph-raw.mkiv b/tex/context/base/grph-raw.mkiv
index 5b488cf58..1c6835564 100644
--- a/tex/context/base/grph-raw.mkiv
+++ b/tex/context/base/grph-raw.mkiv
@@ -45,14 +45,14 @@
\unexpanded\def\bitmapimage[#1]#2%
{\hbox\bgroup
- \getparameters[\??gb][\c!color=rgb,\c!width=,\c!height=,\c!x=,\c!y=,#1]%
- \ctxlua{figures.bitmapimage {
+ \getdummyparameters[\c!color=rgb,\c!width=,\c!height=,\c!x=,\c!y=,#1]%
+ \ctxlua{figures.bitmapimage { % we could pass #1 directly ... todo
data = \!!bs#2\!!es,
- xresolution = "\@@gbx",
- yresolution = "\@@gby",
- colorspace = "\@@gbcolor",
- width = "\@@gbwidth",
- height = "\@@gbheight"
+ colorspace = "\directdummyparameter\c!color",
+ width = "\directdummyparameter\c!width",
+ height = "\directdummyparameter\c!height",
+ xresolution = "\directdummyparameter\c!x",
+ yresolution = "\directdummyparameter\c!y",
}}%
\egroup}
diff --git a/tex/context/base/grph-swf.lua b/tex/context/base/grph-swf.lua
index 88eed021a..0d33d89aa 100644
--- a/tex/context/base/grph-swf.lua
+++ b/tex/context/base/grph-swf.lua
@@ -6,19 +6,20 @@ if not modules then modules = { } end modules ['grph-swf'] = {
license = "see context related readme files"
}
+-- maybe: backends.codeinjections.insertswf
+
local sub, format, match, byte = string.sub, string.format, string.match, string.byte
-local readstring, readnumber = io.readstring, io.readnumber
local concat = table.concat
local floor = math.floor
local tonumber = tonumber
-local tobitstring = number.tobitstring
-
-local todimen = number.todimen
+local readstringr = io.readstring, io.readnumber
+local readnumber = io.readstring, io.readnumber
+local tobitstring = number.tobitstring
+local todimen = number.todimen
local nodeinjections = backends.nodeinjections
-
-local figures = figures
-local context = context
+local figures = figures
+local context = context
local function getheader(name)
local f = io.open(name,"rb")
diff --git a/tex/context/base/grph-trf.mkiv b/tex/context/base/grph-trf.mkiv
index 5984c8a06..d907c1b0c 100644
--- a/tex/context/base/grph-trf.mkiv
+++ b/tex/context/base/grph-trf.mkiv
@@ -52,6 +52,9 @@
\newcount\c_grph_scale_used_x_scale
\newcount\c_grph_scale_used_y_scale
+\let \m_grph_scale_used_x_scale\!!plusone
+\let \m_grph_scale_used_y_scale\!!plusone
+
\newdimen\d_grph_scale_outer_v_size % we cannot manipulate any global vsize !
% scratch:
@@ -66,8 +69,6 @@
\let\finalscaleboxyscale \!!plusone
\let\finalscaleboxwidth \!!zeropoint
\let\finalscaleboxheight \!!zeropoint
-\let\finalscaleboxxfactor\!!hundred
-\let\finalscaleboxyfactor\!!hundred
% we can let sx/sy win (first check)
@@ -78,8 +79,9 @@
\installcommandhandler \??scale {scale} \??scale % we can have instances
\setupscale
- [\c!sx=1,
- \c!sy=1,
+ [\c!sx=\scaleparameter\c!s,
+ \c!sy=\scaleparameter\c!s,
+ \c!s=1,
%\c!scale=,
%\c!xscale=,
%\c!yscale=,
@@ -149,8 +151,6 @@
\global\let\finalscaleboxyscale \!!plusone
\xdef \finalscaleboxwidth {\the\d_grph_scale_wd}%
\xdef \finalscaleboxheight{\the\d_grph_scale_ht}%
- \global\let\finalscaleboxxfactor\!!hundred
- \global\let\finalscaleboxyfactor\!!hundred
%
\forgetall
\dontcomplain
@@ -208,7 +208,7 @@
\def\grph_scale_rounded#1%
{\expandafter\expandafter\expandafter\grph_scale_rounded_indeed
- \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768sp\relax.\relax}
+ \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768\scaledpoint\relax.\relax}
\def\grph_scale_rounded_indeed#1.#2\relax{#1}
@@ -219,9 +219,45 @@
\glet\finalscaleboxxscale\p_sx
\glet\finalscaleboxyscale\p_sy
\ifx\finalscaleboxxscale\empty\let\finalscaleboxxscale\!!plusone\fi
- \ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi
- \xdef\finalscaleboxxfactor{\grph_scale_rounded\finalscaleboxxscale}%
- \xdef\finalscaleboxyfactor{\grph_scale_rounded\finalscaleboxyscale}}
+ \ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi}
+
+\let\grph_scale_calculations_report\relax
+
+% \def\grph_scale_calculations_report
+% {\writestatus
+% {scaled}%
+% {wd:\finalscaleboxwidth,ht:\finalscaleboxheight
+% ,xscale:\finalscaleboxxscale,yscale:\finalscaleboxyscale}}
+
+% \def\grph_scale_calculations_yes
+% {\settrue\c_grph_scale_done
+% % initial values
+% \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\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)
+% \let\m_grph_scale_used_x_scale \!!plusone
+% \let\m_grph_scale_used_y_scale \!!plusone
+% % preparations
+% \setfalse\c_grph_scale_scaling_done
+% \grph_scale_check_parameters
+% % calculators
+% % beware, they operate in sequence, and calculate missing dimensions / messy
+% % grph_scale_by_nature % when? needed?
+% \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
+% % used in actual scaling
+% \xdef\finalscaleboxwidth {\the\d_grph_scale_used_x_size}%
+% \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}%
+% \xdef\finalscaleboxxscale {\luaexpr{\number\c_grph_scale_used_x_scale/1000}}%
+% \xdef\finalscaleboxyscale {\luaexpr{\number\c_grph_scale_used_y_scale/1000}}%
+% \grph_scale_calculations_report}
\def\grph_scale_calculations_yes
{\settrue\c_grph_scale_done
@@ -235,25 +271,23 @@
\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)
+ \let\m_grph_scale_used_x_scale \!!plusone
+ \let\m_grph_scale_used_y_scale \!!plusone
% preparations
\setfalse\c_grph_scale_scaling_done
\grph_scale_check_parameters
% calculators
% beware, they operate in sequence, and calculate missing dimensions / messy
- %grph_scale_by_nature % when? needed?
+ % grph_scale_by_nature % when? needed?
\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)
- \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\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}}
+ \glet\finalscaleboxxscale \m_grph_scale_used_x_scale
+ \glet\finalscaleboxyscale \m_grph_scale_used_y_scale
+ \grph_scale_calculations_report}
\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}}
@@ -292,27 +326,59 @@
\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_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
+ \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\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
+ \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\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_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\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_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size
\grph_scale_by_factor_indeed}
\def\grph_scale_by_factor_d
@@ -333,13 +399,38 @@
\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\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
+ \grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale
+ \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale
+ % \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size\relax % no global needed here
+ % \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size\relax % no global needed here
+ % wrong: we need to recalculate the scale
\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
@@ -369,33 +460,71 @@
\fi
\fi}
+% \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_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}}
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}}
\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}}
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\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\m_grph_scale_used_x_scale\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\m_grph_scale_used_x_scale\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}}
+ {\grph_scale_by_dimension_indeed % weird .. three same cases
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\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\m_grph_scale_used_x_scale\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\m_grph_scale_used_x_scale\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}}
+ {\grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale
+ \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale
+ \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
+ \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\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\m_grph_scale_used_x_scale\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\m_grph_scale_used_x_scale\d_grph_scale_x_size}}
\def\grph_scale_by_dimension_indeed#1#2#3%
{#1\relax
@@ -417,34 +546,63 @@
\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!broad }#1#2#3#4#5{\global#1\dimexpr#5-4\externalfigureparameter\c!bodyfont\relax}
+\setvalue{\??scalenorm\s!unknown}#1#2#3#4#5{\global#1\dimexpr#2\dimexpr\externalfigureparameter\c!bodyfont/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
- \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\grph_scale_calculate_scales#1#2#3#4%
+% {\scratchdimen\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax
+% \c_grph_scale_used_x_scale\scratchdimen
+% \c_grph_scale_used_y_scale\scratchdimen
+% %\writestatus{!!!!}{\the#3/\luaexpr{\number\dimexpr#1\relax/\number\dimexpr#2/1000}}%
+% #3\dimexpr\c_grph_scale_used_x_scale\dimexpr#4/\plusthousand\relax\relax}
+%
+% \def\grph_scale_calculate_scale#1#2#3%
+% {#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\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=\p_scale
+% \fi
+% \else
+% #3=#4%
+% \fi
+% \relax % important ! still ?
+% \global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi
+% \relax}
+
+\def\grph_scale_calculate_scales#1#2%
+ {\edef\m_grph_scale_used_x_scale{\luaexpr{\number#1/\number#2}}%
+ \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale}
+
+% we could inline this:
+%
+% \grph_scale_calculate_scale\m_grph_scale_used_x_scale#1#2
+% \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale
\def\grph_scale_calculate_scale#1#2#3%
- {#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\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=\p_scale
- \fi
- \else
- #3=#4%
- \fi
- \relax % important ! still ?
- \global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi
- \relax}
+ {\edef#1{\luaexpr{\number#2/\number#3}}}
+
+\def\grph_scale_apply_scale#1#2% #1 = parameter / scale can be empty
+ {\edef#1{\luaexpr
+ {\number
+ \ifx#2\empty
+ \ifx \p_scale \empty \plusthousand \else
+ \ifnum\p_scale=\zerocount \plusthousand \else
+ \p_scale \fi\fi
+ \else\ifnum#2=\zerocount
+ \ifx \p_scale \empty \plusthousand \else
+ \ifnum\p_scale=\zerocount \plusthousand \else
+ \p_scale \fi\fi
+ \else
+ #2%
+ \fi\fi
+ /1000}}}
\def\grph_scale_apply_size
{\ifx\p_maxheight\empty
@@ -484,30 +642,34 @@
\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
- \else
- % better 1000 100 10 ranges, evt round 2sp
- \divide\scratchdimen \plusthousand
- \multiply\scratchdimen #3\relax
- \fi
- \scratchdimen-\scratchdimen % beter hier - dan in driver
- \edef#2{\the\scratchdimen}%
- \scratchcounter#3\relax
- \ifnum\scratchcounter>\plustenthousand
- \divide\scratchcounter\plusten
- \scratchdimen\the\scratchcounter\points
- \else
- \scratchdimen\the\scratchcounter\points
- \divide\scratchdimen\plusten
- \fi
- \edef#4{\withoutpt\the\scratchdimen}}
+%\def\grph_scale_convert_large_scale#1#2#3#4%
+% {\scratchdimen#1\relax
+% \ifnum#3=\plusthousand
+% % == scale 1
+% \else
+% % better 1000 100 10 ranges, evt round 2sp
+% \divide\scratchdimen \plusthousand
+% \multiply\scratchdimen #3\relax
+% \fi
+% \scratchdimen-\scratchdimen % beter hier - dan in driver
+% \edef#2{\the\scratchdimen}%
+% \scratchcounter#3\relax
+% \ifnum\scratchcounter>\plustenthousand
+% \divide\scratchcounter\plusten
+% \scratchdimen\the\scratchcounter\points % \the ?
+% \else
+% \scratchdimen\the\scratchcounter\points % \the ?
+% \divide\scratchdimen\plusten
+% \fi
+% \edef#4{\withoutpt\the\scratchdimen}}
+%
+% \def\grph_scale_convert_large_scale#1#2#3#4% less overflow
+% {\edef#2{\ifnum#3=\plusthousand-\the\dimexpr#1\else\luaexpr{-\number#3*\number\dimexpr#1/1000}sp\fi}%
+% \edef#4{\luaexpr{\number#3/10}}}
% \startcombination
-% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {}
-% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {}
+% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {a cow}
+% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {a mill}
% \stopcombination
\def\grph_scale_position
@@ -535,7 +697,7 @@
{\hbox}
\def\grph_scale_fast_yes#1%
- {\edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1pt/1000\relax}% brrr
+ {\edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1\onepoint/1000\relax}% brrr
\let\finalscaleboxyscale\finalscaleboxxscale
\dowithnextboxcs\grph_scale_fast_finish\hbox}
@@ -544,6 +706,19 @@
\box\nextbox
\endgroup}
+\unexpanded\def\fastsxsy#1#2%
+ {\bgroup
+ \edef\p_sx{#1}%
+ \edef\p_sy{#2}%
+ \dowithnextboxcs\grph_scale_fast_sx_xy_finish\hbox}
+
+\def\grph_scale_fast_sx_xy_finish
+ {\grph_scale_check_sx_sy
+ \grph_scale_calculations_nop
+ \grph_scale_apply
+ \box\nextbox
+ \egroup}
+
%D \macros
%D {clip, setupclipping}
%D
@@ -575,8 +750,9 @@
%D
%D \showsetup{setupclipping}
-\unexpanded\def\setupclipping
- {\dodoubleargument\getparameters[\??cp]}
+\installcorenamespace{clipping}
+
+\installdirectcommandhandler \??clipping {clipping}
\unexpanded\def\clip
{\dosingleempty\grph_clip}
@@ -584,62 +760,106 @@
\def\grph_clip[#1]% nb top->bottom left->right
{\bgroup
\iffirstargument
- \getparameters[\??cp][#1]%
+ \setupcurrentclipping[#1]%
\fi
\dowithnextboxcs\grph_clip_finish\hbox}
\def\grph_clip_finish
- {\doifelse\@@cpstate\v!start
+ {\doifelse{\clippingparameter\c!state}\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_yes_finish
- {\ifdim\@@cpwidth>\zeropoint
- \!!dimena\@@cpwidth
- \!!dimenc\@@cphoffset
+ {\ifdim\clippingparameter\c!width>\zeropoint
+ \scratchwidth \clippingparameter\c!width
+ \scratchxoffset\clippingparameter\c!hoffset
\else
- \!!dimena\wd\nextbox
- \divide\!!dimena \@@cpnx
- \!!dimenc\@@cpx\!!dimena
- \advance\!!dimenc -\!!dimena
- \!!dimena\@@cpsx\!!dimena
+ \scratchwidth\dimexpr\wd\nextbox/\clippingparameter\c!nx\relax
+ \scratchxoffset\dimexpr\clippingparameter\c!x\scratchwidth-\scratchwidth\relax
+ \scratchwidth\clippingparameter\c!sx\scratchwidth
\fi
\relax % sure
- \ifdim\@@cpheight>\zeropoint
- \!!dimenb\@@cpheight
- \!!dimend\ht\nextbox
- \advance\!!dimend -\@@cpvoffset
- \advance\!!dimend -\!!dimenb
+ \ifdim\clippingparameter\c!height>\zeropoint
+ \scratchheight\clippingparameter\c!height
+ \scratchyoffset\dimexpr\ht\nextbox-\clippingparameter\c!voffset-\scratchheight\relax
\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 !
+ \scratchheight\dimexpr\ht\nextbox/\clippingparameter\c!ny\relax
+ \scratchyoffset\dimexpr-\clippingparameter\c!y\scratchheight-\clippingparameter\c!sy\scratchheight+\scratchheight\relax
+ \scratchheight\clippingparameter\c!sy\scratchheight
+ \advance\scratchyoffset \ht\nextbox
\fi
- \setbox\nextbox\hbox % old
- {\advance\!!dimenc -\@@cpleftoffset % new !
- \advance\!!dimend -\@@cpbottomoffset % new ! % - added
- \hskip-\!!dimenc\lower\!!dimend\box\nextbox}% old
+ \setbox\nextbox\hbox
+ {\advance\scratchxoffset -\clippingparameter\c!leftoffset \relax
+ \advance\scratchyoffset -\clippingparameter\c!bottomoffset\relax
+ \hskip-\scratchxoffset
+ \lower\scratchyoffset
+ \box\nextbox}%
\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
+ {\advance\scratchwidth \dimexpr\clippingparameter\c!leftoffset +\clippingparameter\c!rightoffset\relax
+ \advance\scratchheight\dimexpr\clippingparameter\c!bottomoffset+\clippingparameter\c!topoffset \relax
+ \dostartclipping{\clippingparameter\c!mp}\scratchwidth\scratchheight
\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
+ \setbox\nextbox\hbox
+ {\hskip-\clippingparameter\c!leftoffset
+ \lower \clippingparameter\c!bottomoffset
+ \box\nextbox}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
\dp\nextbox\zeropoint
\box\nextbox
\egroup}
@@ -650,18 +870,18 @@
\setupclipping
[\c!state=\v!start,
- \c!n=1, % was 2
- \c!nx=\@@cpn,\c!x=1,\c!sx=1,
- \c!ny=\@@cpn,\c!y=1,\c!sy=1,
- \c!width=\!!zeropoint,
- \c!height=\!!zeropoint,
- \c!hoffset=\!!zeropoint,
- \c!voffset=\!!zeropoint,
+ \c!n=\plusone, % was \plustwo
+ \c!nx=\clippingparameter\c!n,\c!x=\plusone,\c!sx=\plusone,
+ \c!ny=\clippingparameter\c!n,\c!y=\plusone,\c!sy=\plusone,
+ \c!width=\zeropoint,
+ \c!height=\zeropoint,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
\c!offset=\zeropoint,
- \c!leftoffset=\@@cpoffset, % \zeropoint,
- \c!rightoffset=\@@cpoffset, % \zeropoint,
- \c!topoffset=\@@cpoffset, % \zeropoint,
- \c!bottomoffset=\@@cpoffset,% \zeropoint,
+ \c!leftoffset=\clippingparameter\c!offset,
+ \c!rightoffset=\clippingparameter\c!offset,
+ \c!topoffset=\clippingparameter\c!offset,
+ \c!bottomoffset=\clippingparameter\c!offset,
\c!mp=]
%D \startbuffer
diff --git a/tex/context/base/grph-u3d.lua b/tex/context/base/grph-u3d.lua
index f2baac2f3..529cd6188 100644
--- a/tex/context/base/grph-u3d.lua
+++ b/tex/context/base/grph-u3d.lua
@@ -8,17 +8,17 @@ if not modules then modules = { } end modules ['grph-u3d'] = {
-- see lpdf-u3d.lua for comment
+-- maybe: backends.codeinjections.insertu3d
+
local trace_inclusion = false trackers.register("figures.inclusion", function(v) trace_inclusion = v end)
local report_u3d = logs.reporter("graphics","u3d")
-local figures = figures
-
+local figures = figures
+local context = context
local nodeinjections = backends.nodeinjections
local todimen = string.todimen
--- maybe todo: backends.codeinjections.insertu3d
-
function figures.checkers.u3d(data)
local dr, du, ds = data.request, data.used, data.status
local width = todimen(dr.width or figures.defaultwidth)
diff --git a/tex/context/base/java-ini.lua b/tex/context/base/java-ini.lua
index 1e98de717..b431a965c 100644
--- a/tex/context/base/java-ini.lua
+++ b/tex/context/base/java-ini.lua
@@ -8,9 +8,10 @@ if not modules then modules = { } end modules ['java-ini'] = {
local format = string.format
local concat = table.concat
-local lpegmatch, lpegP, lpegR, lpegS, lpegC, lpegCarg = lpeg.match, lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Carg
+local lpegmatch, P, S, C, Carg, Cc = lpeg.match, lpeg.P, lpeg.S, lpeg.C, lpeg.Carg, lpeg.Cc
local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
local variables = interfaces.variables
-- todo: don't flush scripts if no JS key
@@ -38,24 +39,24 @@ local function storefunction(s,preamble)
functions[s] = preamble
end
-local uses = lpegP("uses")
-local used = lpegP("used")
-local left = lpegP("{")
-local right = lpegP("}")
-local space = lpegS(" \r\n")
+local uses = P("uses")
+local used = P("used")
+local left = P("{")
+local right = P("}")
+local space = S(" \r\n")
local spaces = space^0
-local braced = left * lpegC((1-right-space)^1) * right
-local unbraced = lpegC((1-space)^1)
+local braced = left * C((1-right-space)^1) * right
+local unbraced = C((1-space)^1)
local name = spaces * (braced + unbraced) * spaces
-local any = lpegP(1)
-local script = lpegC(any^1)
-local funct = lpegP("function")
-local leftp = lpegP("(")
-local rightp = lpegP(")")
-local fname = spaces * funct * spaces * (lpegC((1-space-left-leftp)^1) * lpegCarg(1) / storefunction) * spaces * leftp
-
-local parsecode = name * ((uses * name) + lpeg.Cc("")) * spaces * script
-local parsepreamble = name * ((used * name) + lpeg.Cc("")) * spaces * script
+local any = P(1)
+local script = C(any^1)
+local funct = P("function")
+local leftp = P("(")
+local rightp = P(")")
+local fname = spaces * funct * spaces * (C((1-space-left-leftp)^1) * Carg(1) / storefunction) * spaces * leftp
+
+local parsecode = name * ((uses * name) + Cc("")) * spaces * script
+local parsepreamble = name * ((used * name) + Cc("")) * spaces * script
local parsefunctions = (fname + any)^0
function javascripts.storecode(str)
@@ -112,7 +113,7 @@ end
function javascripts.usepreamblenow(name) -- now later
if name and name ~= "" and name ~= variables.reset then -- todo: reset
- local names = utilities.parsers.settings_to_array(name)
+ local names = settings_to_array(name)
for i=1,#names do
local somename = names[i]
if not preambled[somename] then
diff --git a/tex/context/base/l-boolean.lua b/tex/context/base/l-boolean.lua
index 2d502f164..2b94de76b 100644
--- a/tex/context/base/l-boolean.lua
+++ b/tex/context/base/l-boolean.lua
@@ -16,28 +16,49 @@ function boolean.tonumber(b)
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
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
elseif str == "true" then
return true
elseif str == "false" then
return false
+ elseif not tolerant then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
else
- return str
+ return str == "yes" or str == "on" or str == "t"
end
end
string.toboolean = toboolean
+function string.booleanstring(str)
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
+ else
+ return str == "yes" or str == "on" or str == "t"
+ end
+end
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua
index 71de3114e..3deb660ce 100644
--- a/tex/context/base/l-dir.lua
+++ b/tex/context/base/l-dir.lua
@@ -25,6 +25,24 @@ local isdir = lfs.isdir
local isfile = lfs.isfile
local currentdir = lfs.currentdir
+-- in case we load outside luatex
+
+if not isdir then
+ function isdir(name)
+ local a = attributes(name)
+ return a and a.mode == "directory"
+ end
+ lfs.isdir = isdir
+end
+
+if not isfile then
+ function isfile(name)
+ local a = attributes(name)
+ return a and a.mode == "file"
+ end
+ lfs.isfile = isfile
+end
+
-- handy
function dir.current()
diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua
index edfbc0f92..bea4ef0aa 100644
--- a/tex/context/base/l-file.lua
+++ b/tex/context/base/l-file.lua
@@ -34,7 +34,7 @@ local function nameonly(name)
return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$",""))
end
-local function extname(name,default)
+local function suffixonly(name,default)
return match(name,"^.+%.([^/\\]-)$") or default or ""
end
@@ -43,11 +43,16 @@ local function splitname(name)
return n or name, s or ""
end
-file.basename = basename
-file.dirname = dirname
-file.nameonly = nameonly
-file.extname = extname
-file.suffix = extname
+file.basename = basename
+
+file.pathpart = dirname
+file.dirname = dirname
+
+file.nameonly = nameonly
+
+file.suffixonly = suffixonly
+file.extname = suffixonly -- obsolete
+file.suffix = suffixonly
function file.removesuffix(filename)
return (gsub(filename,"%.[%a%d]+$",""))
@@ -193,6 +198,11 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
+function file.size(name)
+ local a = attributes(name)
+ return a and a.size or 0
+end
+
-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -323,7 +333,7 @@ end
--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1
---~ function file.extname(name)
+--~ function file.suffixonly(name)
--~ return lpegmatch(pattern,name) or ""
--~ end
@@ -385,7 +395,7 @@ end
--~ end
--~ end
---~ local test = file.extname
+--~ local test = file.suffixonly
--~ local test = file.basename
--~ local test = file.dirname
--~ local test = file.addsuffix
@@ -431,6 +441,7 @@ local drive = C(R("az","AZ")) * P(":")
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 rest = C(P(1)^0)
drive = drive + Cc("")
path = path + Cc("")
@@ -439,7 +450,8 @@ 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)
+local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures
+local pattern_d = path * rest
function file.splitname(str,splitdrive)
if splitdrive then
@@ -449,6 +461,10 @@ function file.splitname(str,splitdrive)
end
end
+function file.splitbase(str)
+ return lpegmatch(pattern_d,str) -- returns path, base+suffix
+end
+
function file.nametotable(str,splitdrive) -- returns table
local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
if splitdrive then
@@ -470,6 +486,8 @@ function file.nametotable(str,splitdrive) -- returns table
end
end
+-- print(file.splitbase("a/b/c.txt"))
+
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
--
-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
diff --git a/tex/context/base/l-io.lua b/tex/context/base/l-io.lua
index 4f27dc1dc..657b755b8 100644
--- a/tex/context/base/l-io.lua
+++ b/tex/context/base/l-io.lua
@@ -17,14 +17,14 @@ else
io.fileseparator, io.pathseparator = "/" , ":"
end
-function io.loaddata(filename,textmode)
+function io.loaddata(filename,textmode) -- return nil if empty
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
local data = f:read('*all')
f:close()
- return data
- else
- return nil
+ if #data > 0 then
+ return data
+ end
end
end
@@ -46,6 +46,45 @@ function io.savedata(filename,data,joiner)
end
end
+function io.loadlines(filename,n) -- return nil if empty
+ local f = io.open(filename,'r')
+ if f then
+ if n then
+ local lines = { }
+ for i=1,n do
+ local line = f:read("*lines")
+ if line then
+ lines[#lines+1] = line
+ else
+ break
+ end
+ end
+ f:close()
+ lines = concat(lines,"\n")
+ if #lines > 0 then
+ return lines
+ end
+ else
+ local line = f:read("*line") or ""
+ assert(f:close())
+ if #line > 0 then
+ return line
+ end
+ end
+ end
+end
+
+function io.loadchunk(filename,n)
+ local f = io.open(filename,'rb')
+ if f then
+ local data = f:read(n or 1024)
+ f:close()
+ if #data > 0 then
+ return data
+ end
+ end
+end
+
function io.exists(filename)
local f = io.open(filename)
if f == nil then
diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua
index 13294ab0d..d92b722ed 100644
--- a/tex/context/base/l-lpeg.lua
+++ b/tex/context/base/l-lpeg.lua
@@ -13,6 +13,8 @@ local lpeg = require("lpeg")
-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+-- some code will move to unicode and string
+
local report = texio and texio.write_nl or print
-- local lpmatch = lpeg.match
@@ -49,8 +51,8 @@ local report = texio and texio.write_nl or print
-- 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
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-- 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.
@@ -58,9 +60,8 @@ local byte, char, gmatch = string.byte, string.char, string.gmatch
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 P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
local utfcharacters = string.utfcharacters
local utfgmatch = unicode and unicode.utf8.gmatch
@@ -111,6 +112,10 @@ patterns.utf8char = utf8char
patterns.validutf8 = validutf8char
patterns.validutf8char = validutf8char
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+
patterns.digit = digit
patterns.sign = sign
patterns.cardinal = sign^0 * digit^1
@@ -130,16 +135,16 @@ 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.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
patterns.newline = newline
patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.nonspacer = 1 - spacer
+patterns.nonwhitespace = 1 - whitespace
patterns.equal = P("=")
patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.commaspacer = P(",") * spacer^0
patterns.period = P(".")
patterns.colon = P(":")
patterns.semicolon = P(";")
@@ -154,6 +159,10 @@ patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
@@ -164,8 +173,17 @@ patterns.beginline = #(1-newline)
-- 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?
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
end
function lpeg.splitter(pattern, action)
@@ -214,13 +232,13 @@ function string.splitup(str,separator)
if not separator then
separator = ","
end
- return match(splitters_m[separator] or splitat(separator),str)
+ return lpegmatch(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 p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
+--~ local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
+--~ local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
+--~ local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
local cache = { }
@@ -230,16 +248,20 @@ function lpeg.split(separator,str)
c = tsplitat(separator)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
end
- return match(c,str)
end
local spacing = patterns.spacer^0 * newline -- sort of strip
@@ -252,7 +274,7 @@ patterns.textline = content
--~ local linesplitter = Ct(content^0)
--~
--~ function string.splitlines(str)
---~ return match(linesplitter,str)
+--~ return lpegmatch(linesplitter,str)
--~ end
local linesplitter = tsplitat(newline)
@@ -260,7 +282,7 @@ local linesplitter = tsplitat(newline)
patterns.linesplitter = linesplitter
function string.splitlines(str)
- return match(linesplitter,str)
+ return lpegmatch(linesplitter,str)
end
local utflinesplitter = utfbom^-1 * tsplitat(newline)
@@ -268,7 +290,58 @@ local utflinesplitter = utfbom^-1 * tsplitat(newline)
patterns.utflinesplitter = utflinesplitter
function string.utfsplitlines(str)
- return match(utflinesplitter,str or "")
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
+local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
+
+function string.utfsplit(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+-- inspect(string.utfsplit("a b c d"))
+-- inspect(string.utfsplit("a b c d",true))
+
+-- -- alternative 1: 0.77
+--
+-- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
+--
+-- function string.utflength(str)
+-- return #lpegmatch(utfcharcounter,str or "")
+-- end
+--
+-- -- alternative 2: 1.70
+--
+-- local n = 0
+--
+-- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
+--
+-- function string.utflength(str)
+-- n = 0
+-- lpegmatch(utfcharcounter,str or "")
+-- return n
+-- end
+--
+-- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+local n = 0
+
+local utfcharcounter = utfbom^-1 * Cs ( (
+ Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+)^0 )
+
+function string.utflength(str)
+ n = 0
+ lpegmatch(utfcharcounter,str or "")
+ return n
end
--~ lpeg.splitters = cache -- no longer public
@@ -283,7 +356,7 @@ function lpeg.checkedsplit(separator,str)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.checkedsplit(str,separator)
@@ -294,7 +367,7 @@ function string.checkedsplit(str,separator)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
--~ from roberto's site:
@@ -309,10 +382,10 @@ 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 s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]")
local cache = { }
@@ -345,11 +418,11 @@ function lpeg.keeper(str)
end
function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
+ return (P(str) + P(true)) * Cs(anything^0)
end
function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
+ return Cs((1 - P(str) * endofstring)^0)
end
-- Just for fun I looked at the used bytecode and
@@ -358,8 +431,22 @@ end
function lpeg.replacer(one,two)
if type(one) == "table" then
local no = #one
- if no > 0 then
- local p
+ local p
+ if no == 0 then
+ for k, v in next, one do
+ local pp = P(k) / v
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ return Cs(((1-one)^1 + one/two)^0)
+ else
for i=1,no do
local o = one[i]
local pp = P(o[1]) / o[2]
@@ -372,11 +459,16 @@ function lpeg.replacer(one,two)
return Cs((p + 1)^0)
end
else
+ one = P(one)
two = two or ""
- return Cs((P(one)/two + 1)^0)
+ return Cs(((1-one)^1 + one/two)^0)
end
end
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -404,14 +496,14 @@ function lpeg.balancer(left,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"))
+--~ print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
+--~ print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
+--~ print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
+--~ print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
+--~ print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
+--~ print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
+--~ print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
+--~ print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
--~ -- slower:
--~
@@ -425,7 +517,7 @@ local nany = utf8char/""
function lpeg.counter(pattern)
pattern = Cs((P(pattern)/" " + nany)^0)
return function(str)
- return #match(pattern,str)
+ return #lpegmatch(pattern,str)
end
end
@@ -439,7 +531,7 @@ if utfgmatch then
end
return n
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -454,9 +546,9 @@ else
p = Cs((P(what)/" " + nany)^0)
cache[p] = p
end
- return #match(p,str)
+ return #lpegmatch(p,str)
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -483,7 +575,7 @@ 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)
+ return lpegmatch(simple and s or p,str)
end
-- utf extensies
@@ -530,7 +622,7 @@ else
p = P(uc)
end
end
- match((utf8char/f)^0,str)
+ lpegmatch((utf8char/f)^0,str)
return p
end
@@ -546,7 +638,7 @@ function lpeg.UR(str,more)
first = str
last = more or first
else
- first, last = match(range,str)
+ first, last = lpegmatch(range,str)
if not last then
return P(str)
end
@@ -582,11 +674,15 @@ end
--~ print(lpeg.count("äáàa",lpeg.UR("àá")))
--~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
if type(list) ~= "table" then
list = { list, ... }
end
- -- sort(list) -- longest match first
+ -- table.sort(list) -- longest match first
local p = P(list[1])
for l=2,#list do
p = p + P(list[l])
@@ -594,10 +690,6 @@ function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
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.
@@ -754,3 +846,21 @@ end
-- utfchar(0x202F), -- narrownobreakspace
-- utfchar(0x205F), -- math thinspace
-- } )
+
+-- handy from within tex:
+
+local lpegmatch = lpeg.match
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- strips leading and trailing spaces and collapsed all other spaces
+
+local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
+
+function string.collapsespaces(str)
+ return lpegmatch(pattern,str)
+end
diff --git a/tex/context/base/l-md5.lua b/tex/context/base/l-md5.lua
index 1d471c966..6abf2e17d 100644
--- a/tex/context/base/l-md5.lua
+++ b/tex/context/base/l-md5.lua
@@ -31,15 +31,30 @@ if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
--~ function md5.dec(str) return (gsub(md5.sum(str),".",remap)) end
--~ end
-function file.needs_updating(oldname,newname,threshold) -- size modification access change
- local oldtime = lfs.attributes(oldname, modification)
- local newtime = lfs.attributes(newname, modification)
- if newtime >= oldtime then
- return false
- elseif oldtime - newtime < (threshold or 1) then
- return false
+function file.needsupdating(oldname,newname,threshold) -- size modification access change
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime = lfs.attributes(newname,"modification")
+ if not newtime then
+ return true -- no new file, so no updating needed
+ elseif newtime >= oldtime then
+ return false -- new file definitely needs updating
+ elseif oldtime - newtime < (threshold or 1) then
+ return false -- new file is probably still okay
+ else
+ return true -- new file has to be updated
+ end
else
- return true
+ return false -- no old file, so no updating needed
+ end
+end
+
+file.needs_updating = file.needsupdating
+
+function file.syncmtimes(oldname,newname)
+ local oldtime = lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
end
end
@@ -61,7 +76,7 @@ function file.loadchecksum(name)
return nil
end
-function file.savechecksum(name, checksum)
+function file.savechecksum(name,checksum)
if not checksum then checksum = file.checksum(name) end
if checksum then
io.savedata(name .. ".md5",checksum)
diff --git a/tex/context/base/l-number.lua b/tex/context/base/l-number.lua
index b1ffb9ca9..a4dbe3bdf 100644
--- a/tex/context/base/l-number.lua
+++ b/tex/context/base/l-number.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['l-number'] = {
-- this module will be replaced when we have the bit library
-local tostring = tostring
+local tostring, tonumber = tostring, tonumber
local format, floor, match, rep = string.format, math.floor, string.match, string.rep
local concat, insert = table.concat, table.insert
local lpegmatch = lpeg.match
@@ -72,11 +72,11 @@ function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
end
function number.setbit(x, p)
- return hasbit(x, p) and x or x + p
+ return (x % (p + p) >= p) and x or x + p
end
function number.clearbit(x, p)
- return hasbit(x, p) and x - p or x
+ return (x % (p + p) >= p) and x - p or x
end
--~ function number.tobitstring(n)
@@ -128,3 +128,7 @@ end
--~ print(number.tobitstring(0xFF))
--~ print(number.tobitstring(46260767936,8))
--~ print(#number.tobitstring(46260767936,6))
+
+function number.valid(str,default)
+ return tonumber(str) or default or nil
+end
diff --git a/tex/context/base/l-os.lua b/tex/context/base/l-os.lua
index f9bd46e51..799f44957 100644
--- a/tex/context/base/l-os.lua
+++ b/tex/context/base/l-os.lua
@@ -22,17 +22,28 @@ if not modules then modules = { } end modules ['l-os'] = {
-- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
-- os.platform : extended os.name with architecture
+-- os.sleep() => socket.sleep()
+-- math.randomseed(tonumber(string.sub(string.reverse(tostring(math.floor(socket.gettime()*10000))),1,6)))
+
-- maybe build io.flush in os.execute
local os = os
+local date, time = os.date, os.time
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
+local random, ceil, randomseed = math.random, math.ceil, math.randomseed
+local rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring = rawget, rawset, type, getmetatable, setmetatable, tonumber, tostring
-- The following code permits traversing the environment table, at least
-- in luatex. Internally all environment names are uppercase.
+-- The randomseed in Lua is not that random, although this depends on the operating system as well
+-- as the binary (Luatex is normally okay). But to be sure we set the seed anyway.
+
+math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+
+randomseed(math.initialseed)
+
if not os.__getenv__ then
os.__getenv__ = os.getenv
@@ -136,12 +147,14 @@ else
os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
+local launchers = {
+ windows = "start %s",
+ macosx = "open %s",
+ unix = "$BROWSER %s &> /dev/null &",
+}
+
function os.launch(str)
- if os.type == "windows" then
- os.execute("start " .. str) -- os.spawn ?
- else
- os.execute(str .. " &") -- os.spawn ?
- end
+ os.execute(format(launchers[os.name] or launchers.unix,str))
end
if not os.times then
@@ -357,7 +370,7 @@ end
local d
function os.timezone(delta)
- d = d or tonumber(tonumber(os.date("%H")-os.date("!%H")))
+ d = d or tonumber(tonumber(date("%H")-date("!%H")))
if delta then
if d > 0 then
return format("+%02i:00",d)
@@ -369,6 +382,44 @@ function os.timezone(delta)
end
end
+local timeformat = format("%%s%s",os.timezone(true))
+local dateformat = "!%Y-%m-%d %H:%M:%S"
+
+function os.fulltime(t,default)
+ t = tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = nil
+ end
+ return format(timeformat,date(dateformat,t))
+end
+
+local dateformat = "%Y-%m-%d %H:%M:%S"
+
+function os.localtime(t,default)
+ t = tonumber(t) or 0
+ if t > 0 then
+ -- valid time
+ elseif default then
+ return default
+ else
+ t = nil
+ end
+ return date(dateformat,t)
+end
+
+function os.converttime(t,default)
+ local t = tonumber(t)
+ if t and t > 0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
+end
+
local memory = { }
local function which(filename)
diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua
index 989e57f75..03616aa19 100644
--- a/tex/context/base/l-string.lua
+++ b/tex/context/base/l-string.lua
@@ -112,7 +112,24 @@ function string.topattern(str,lowercase,strict)
end
end
+
+function string.valid(str,default)
+ return (type(str) == "string" and str ~= "" and str) or default or nil
+end
+
-- obsolete names:
string.quote = string.quoted
string.unquote = string.unquoted
+
+-- handy fallback
+
+string.itself = function(s) return s end
+
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
index 337ce054a..80f28c2cd 100644
--- a/tex/context/base/l-table.lua
+++ b/tex/context/base/l-table.lua
@@ -6,7 +6,8 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string
+local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local table, string = table, string
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
@@ -17,6 +18,8 @@ local getinfo = debug.getinfo
-- impact on ConTeXt was not that large; the remaining ipairs already
-- have been replaced. In a similar fashion we also hardly used pairs.
--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -76,12 +79,16 @@ function table.strip(tab)
end
function table.keys(t)
- local keys, k = { }, 0
- for key, _ in next, t do
- k = k + 1
- keys[k] = key
+ if t then
+ local keys, k = { }, 0
+ for key, _ in next, t do
+ k = k + 1
+ keys[k] = key
+ end
+ return keys
+ else
+ return { }
end
- return keys
end
local function compare(a,b)
@@ -94,41 +101,49 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
- for key,_ in next, tab do
- s = s + 1
- srt[s] = key
- if category == 3 then
- -- no further check
- else
- local tkey = type(key)
- if tkey == "string" then
- category = (category == 2 and 3) or 1
- elseif tkey == "number" then
- category = (category == 1 and 3) or 2
+ if tab then
+ local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ for key,_ in next, tab do
+ s = s + 1
+ srt[s] = key
+ if category == 3 then
+ -- no further check
else
- category = 3
+ local tkey = type(key)
+ if tkey == "string" then
+ category = (category == 2 and 3) or 1
+ elseif tkey == "number" then
+ category = (category == 1 and 3) or 2
+ else
+ category = 3
+ end
end
end
- end
- if category == 0 or category == 3 then
- sort(srt,compare)
+ if category == 0 or category == 3 then
+ sort(srt,compare)
+ else
+ sort(srt)
+ end
+ return srt
else
- sort(srt)
+ return { }
end
- return srt
end
local function sortedhashkeys(tab) -- fast one
- local srt, s = { }, 0
- for key,_ in next, tab do
- if key then
- s= s + 1
- srt[s] = key
+ if tab then
+ local srt, s = { }, 0
+ for key,_ in next, tab do
+ if key then
+ s= s + 1
+ srt[s] = key
+ end
end
+ sort(srt)
+ return srt
+ else
+ return { }
end
- sort(srt)
- return srt
end
table.sortedkeys = sortedkeys
@@ -153,7 +168,7 @@ end
table.sortedhash = sortedhash
table.sortedpairs = sortedhash
-function table.append(t, list)
+function table.append(t,list)
local n = #t
for i=1,#list do
n = n + 1
@@ -388,12 +403,26 @@ local function do_serialize(root,name,depth,level,indexed)
end
-- we could check for k (index) being number (cardinal)
if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- if compact then
+ -- -- NOT: for k=1,#root do (we need to quit at nil)
+ -- for k,v in ipairs(root) do -- can we use next?
+ -- if not first then first = k end
+ -- last = last + 1
+ -- end
+ -- end
+ local first, last = nil, 0
if compact then
- -- NOT: for k=1,#root do (we need to quit at nil)
- for k,v in ipairs(root) do -- can we use next?
- if not first then first = k end
- last = last + 1
+ last = #root
+ for k=1,last do
+-- if not root[k] then
+ if root[k] == nil then
+ last = k - 1
+ break
+ end
+ end
+ if last > 0 then
+ first = 1
end
end
local sk = sortedkeys(root)
@@ -885,23 +914,27 @@ function table.reversed(t)
end
end
-function table.sequenced(t,sep,simple) -- hash only
- local s, n = { }, 0
- for k, v in sortedhash(t) do
- if simple then
- if v == true then
- n = n + 1
- s[n] = k
- elseif v and v~= "" then
+function table.sequenced(t,sep) -- hash only
+ if t then
+ local s, n = { }, 0
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ n = n + 1
+ s[n] = k
+ elseif v and v~= "" then
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
+ end
+ else
n = n + 1
s[n] = k .. "=" .. tostring(v)
end
- else
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
end
+ return concat(s, sep or " | ")
+ else
+ return ""
end
- return concat(s, sep or " | ")
end
function table.print(t,...)
diff --git a/tex/context/base/l-unicode.lua b/tex/context/base/l-unicode.lua
index f4480e93c..630c34960 100644
--- a/tex/context/base/l-unicode.lua
+++ b/tex/context/base/l-unicode.lua
@@ -6,57 +6,253 @@ if not modules then modules = { } end modules ['l-unicode'] = {
license = "see context related readme files"
}
+-- this module will be reorganized
+
+-- todo: utf.sub replacement (used in syst-aux)
+
+local concat = table.concat
+local type = type
+local P, C, R, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Ct
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local utftype = patterns.utftype
+local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
+local utfsplitlines = string.utfsplitlines
+
if not unicode then
- unicode = { utf8 = { } }
+ unicode = { }
+
+end
+
+local unicode = unicode
+
+utf = utf or unicode.utf8
+
+if not utf then
+
+ utf8 = { }
+ unicode.utf8 = utf8
+ utf = utf8
+
+end
+
+if not utf.char then
local floor, char = math.floor, string.char
- function unicode.utf8.utfchar(n)
+ function utf.char(n)
if n < 0x80 then
+ -- 0aaaaaaa : 0x80
return char(n)
elseif n < 0x800 then
+ -- 110bbbaa : 0xC0 : n >> 6
+ -- 10aaaaaa : 0x80 : n & 0x3F
return char(
0xC0 + floor(n/0x40),
0x80 + (n % 0x40)
)
elseif n < 0x10000 then
+ -- 1110bbbb : 0xE0 : n >> 12
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
return char(
0xE0 + floor(n/0x1000),
0x80 + (floor(n/0x40) % 0x40),
0x80 + (n % 0x40)
)
- elseif n < 0x40000 then
+ elseif n < 0x200000 then
+ -- 11110ccc : 0xF0 : n >> 18
+ -- 10ccbbbb : 0x80 : (n >> 12) & 0x3F
+ -- 10bbbbaa : 0x80 : (n >> 6) & 0x3F
+ -- 10aaaaaa : 0x80 : n & 0x3F
+ -- dddd : ccccc - 1
return char(
- 0xF0 + floor(n/0x40000),
- 0x80 + floor(n/0x1000),
+ 0xF0 + floor(n/0x40000),
+ 0x80 + (floor(n/0x1000) % 0x40),
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 "?"
+ return ""
end
end
end
-local unicode = unicode
+if not utf.byte then
-utf = utf or unicode.utf8
+ local utf8byte = patterns.utf8byte
-local concat = table.concat
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
-local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-local type = type
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
-local utfsplitlines = string.utfsplitlines
+end
+
+local utfchar, utfbyte = utf.char, utf.byte
+
+-- As we want to get rid of the (unmaintained) utf library we implement our own
+-- variants (in due time an independent module):
+
+function unicode.filetype(data)
+ return data and lpegmatch(utftype,data) or "unknown"
+end
+
+local toentities = 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 } )
+--~
+--~ collectgarbage("collect")
+--~ local u = collectgarbage("count")*1024
+--~ local t = os.clock()
+--~ for i=1,1000 do
+--~ for i=1,600 do
+--~ local a = utfchr[i]
+--~ end
+--~ end
+--~ print(os.clock()-t,collectgarbage("count")*1024-u)
+
+--~ collectgarbage("collect")
+--~ local t = os.clock()
+--~ for i=1,1000 do
+--~ for i=1,600 do
+--~ local a = utfchar(i)
+--~ 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 one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+-- actually one of them is already utf ... sort of useless this one
+
+-- function utf.char(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
+--
+-- merge into:
+
+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
+
+local validatedutf = Cs (
+ (
+ patterns.utf8one
+ + patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ + P(1) / "�"
+ )^0
+)
+
+patterns.validatedutf = validatedutf
+
+function string.validutf(str)
+ return lpegmatch(validatedutf,str)
+end
+
+
+utf.length = string.utflength
+utf.split = string.utfsplit
+utf.splitines = string.utfsplitlines
+utf.valid = string.validutf
+
+if not utf.len then
+ utf.len = utf.length
+end
+
+-- a replacement for simple gsubs:
+
+local utf8char = patterns.utf8char
+
+function utf.remapper(mapping)
+ local pattern = Cs((utf8char/mapping)^0)
+ return function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end, pattern
+end
+
+-- local remap = utf.remapper { a = 'd', b = "c", c = "b", d = "a" }
+-- print(remap("abcd 1234 abcd"))
-- 0 EF BB BF UTF-8
-- 1 FF FE UTF-16-little-endian
@@ -352,11 +548,22 @@ local function big(c)
end
end
+-- function unicode.utf8_to_utf16(str,littleendian)
+-- if littleendian then
+-- return char(255,254) .. utfgsub(str,".",little)
+-- else
+-- return char(254,255) .. utfgsub(str,".",big)
+-- end
+-- end
+
+local _, l_remap = utf.remapper(little)
+local _, b_remap = utf.remapper(big)
+
function unicode.utf8_to_utf16(str,littleendian)
if littleendian then
- return char(255,254) .. utfgsub(str,".",little)
+ return char(255,254) .. lpegmatch(l_remap,str)
else
- return char(254,255) .. utfgsub(str,".",big)
+ return char(254,255) .. lpegmatch(b_remap,str)
end
end
@@ -377,107 +584,10 @@ function unicode.xstring(s)
return format("0x%05X",type(s) == "number" and s or utfbyte(s))
end
---~ print(unicode.utfcodes(str))
+--
-local lpegmatch = lpeg.match
-local patterns = lpeg.patterns
-local utftype = patterns.utftype
+local pattern = Ct(C(patterns.utf8char)^0)
-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 } )
---~
---~ collectgarbage("collect")
---~ local u = collectgarbage("count")*1024
---~ local t = os.clock()
---~ for i=1,1000 do
---~ for i=1,600 do
---~ local a = utfchr[i]
---~ end
---~ end
---~ print(os.clock()-t,collectgarbage("count")*1024-u)
-
---~ collectgarbage("collect")
---~ local t = os.clock()
---~ for i=1,1000 do
---~ for i=1,600 do
---~ local a = utfchar(i)
---~ 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)
-
--- actually one of them is already utf ... sort of useless this one
-
-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
-
-local validatedutf = Cs (
- (
- patterns.utf8one
- + patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- + P(1) / "�"
- )^0
-)
-
-patterns.validatedutf = validatedutf
-
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
+function utf.totable(str)
+ return lpegmatch(pattern,str)
end
diff --git a/tex/context/base/l-url.lua b/tex/context/base/l-url.lua
index 69f32cc39..ab5002881 100644
--- a/tex/context/base/l-url.lua
+++ b/tex/context/base/l-url.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['l-url'] = {
local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find
local concat = table.concat
local tonumber, type = tonumber, type
-local P, C, R, S, Cs, Cc, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct
+local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V
local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer
-- from wikipedia:
@@ -42,15 +42,19 @@ local endofstring = P(-1)
local hexdigit = R("09","AF","af")
local plus = P("+")
local nothing = Cc("")
-local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
+local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar
+local escaped = (plus / " ") + escapedchar
-- 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
+--
+-- maybe we should already split the query (better for unescaping as = & can be part of a value
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)
+----- querystr = Cs((escaped+(1- hash))^0)
+local querystr = Cs(( (1- hash))^0)
local fragmentstr = Cs((escaped+(1- endofstring))^0)
local scheme = schemestr * colon + nothing
@@ -65,11 +69,20 @@ local parser = Ct(validurl)
lpegpatterns.url = validurl
lpegpatterns.urlsplitter = parser
-local escapes = { } ; for i=0,255 do escapes[i] = format("%%%02X",i) end
+local escapes = { }
+
+setmetatable(escapes, { __index = function(t,k)
+ local v = format("%%%02X",byte(k))
+ t[k] = v
+ return v
+end })
-local escaper = Cs((R("09","AZ","az") + S("-./_") + P(1) / escapes)^0)
+local escaper = Cs((R("09","AZ","az")^1 + P(" ")/"%%20" + S("-./_")^1 + P(1) / escapes)^0) -- space happens most
+local unescaper = Cs((escapedchar + 1)^0)
-lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaped = escapedchar
+lpegpatterns.urlescaper = escaper
+lpegpatterns.urlunescaper = unescaper
-- todo: reconsider Ct as we can as well have five return values (saves a table)
-- so we can have two parsers, one with and one without
@@ -81,8 +94,12 @@ end
local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
local function hasscheme(str)
- local scheme = lpegmatch(isscheme,str) -- at least one character
- return scheme ~= "" and scheme or false
+ if str then
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
+ else
+ return false
+ end
end
--~ print(hasscheme("home:"))
@@ -103,10 +120,32 @@ local rootbased = P("/")
local barswapper = replacer("|",":")
local backslashswapper = replacer("\\","/")
+-- queries:
+
+local equal = P("=")
+local amp = P("&")
+local key = Cs(((escapedchar+1)-equal )^0)
+local value = Cs(((escapedchar+1)-amp -endofstring)^0)
+
+local splitquery = Cf ( Ct("") * P { "sequence",
+ sequence = V("pair") * (amp * V("pair"))^0,
+ pair = Cg(key * equal * value),
+}, rawset)
+
+-- hasher
+
local function hashed(str) -- not yet ok (/test?test)
+ if str == "" then
+ return {
+ scheme = "invalid",
+ original = str,
+ }
+ end
local s = split(str)
- local somescheme = s[1] ~= ""
- local somequery = s[4] ~= ""
+ local rawscheme = s[1]
+ local rawquery = s[4]
+ local somescheme = rawscheme ~= ""
+ local somequery = rawquery ~= ""
if not somescheme and not somequery then
s = {
scheme = "file",
@@ -122,14 +161,17 @@ local function hashed(str) -- not yet ok (/test?test)
local authority, path, filename = s[2], s[3]
if authority == "" then
filename = path
+ elseif path == "" then
+ filename = ""
else
filename = authority .. "/" .. path
end
s = {
- scheme = s[1],
+ scheme = rawscheme,
authority = authority,
path = path,
- query = s[4],
+ query = lpegmatch(unescaper,rawquery), -- unescaped, but possible conflict with & and =
+ queries = lpegmatch(splitquery,rawquery), -- split first and then unescaped
fragment = s[5],
original = str,
noscheme = false,
@@ -139,6 +181,8 @@ local function hashed(str) -- not yet ok (/test?test)
return s
end
+-- inspect(hashed("template://test"))
+
-- Here we assume:
--
-- files: /// = relative
@@ -189,23 +233,64 @@ function url.construct(hash) -- dodo: we need to escape !
return lpegmatch(escaper,concat(fullurl))
end
-function url.filename(filename)
+function url.filename(filename) -- why no lpeg here ?
local t = hashed(filename)
return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename
end
+local function escapestring(str)
+ return lpegmatch(escaper,str)
+end
+
+url.escape = escapestring
+
+-- function url.query(str) -- separator could be an option
+-- if type(str) == "string" then
+-- local t = { }
+-- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
+-- t[k] = v
+-- end
+-- return t
+-- else
+-- return str
+-- end
+-- end
+
function url.query(str)
if type(str) == "string" then
- local t = { }
- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
- t[k] = v
- end
- return t
+ return lpegmatch(splitquery,str) or ""
else
return str
end
end
+function url.toquery(data)
+ local td = type(data)
+ if td == "string" then
+ return #str and escape(data) or nil -- beware of double escaping
+ elseif td == "table" then
+ if next(data) then
+ local t = { }
+ for k, v in next, data do
+ t[#t+1] = format("%s=%s",k,escapestring(v))
+ end
+ return concat(t,"&")
+ end
+ else
+ -- nil is a signal that no query
+ end
+end
+
+-- /test/ | /test | test/ | test => test
+
+function url.barepath(path)
+ if not path or path == "" then
+ return ""
+ else
+ return (gsub(path,"^/?(.-)/?$","%1"))
+ end
+end
+
--~ print(url.filename("file:///c:/oeps.txt"))
--~ print(url.filename("c:/oeps.txt"))
--~ print(url.filename("file:///oeps.txt"))
@@ -220,6 +305,9 @@ end
--~ print(table.serialize(t))
--~ end
+--~ inspect(url.hashed("http://www.pragma-ade.com/test%20test?test=test%20test&x=123%3d45"))
+--~ inspect(url.hashed("http://www.pragma-ade.com/test%20test?test=test%20test&x=123%3d45"))
+
--~ test("sys:///./colo-rgb")
--~ test("/data/site/output/q2p-develop/resources/ecaboperception4_res/topicresources/58313733/figuur-cow.jpg")
diff --git a/tex/context/base/lang-def.lua b/tex/context/base/lang-def.lua
index 80ff13beb..c6bbcf3ae 100644
--- a/tex/context/base/lang-def.lua
+++ b/tex/context/base/lang-def.lua
@@ -1,15 +1,18 @@
-if not modules then modules = { } end modules ['lang-ini'] = {
+if not modules then modules = { } end modules ['lang-def'] = {
version = 1.001,
comment = "companion to lang-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
+ -- dataonly = true, -- saves 10K
}
+local rawget = rawget
local lower = string.lower
languages = languages or { }
local languages = languages
+languages.data = languages.data or { }
local data = languages.data
local allocate = utilities.storage.allocate
@@ -376,50 +379,54 @@ local contexts = { } data.contexts = contexts
local records = { } data.records = records
for k=1,#specifications do
- local v = specifications[k]
- if v.variant then
- variants[v.variant] = v
+ local specification = specifications[k]
+ local variant = specification.variant
+ if variant then
+ variants[lower(variant)] = specification
end
- if v.opentype then
- opentypes[v.opentype] = v
+ local opentype = specification.opentype
+ if opentype then
+ opentypes[lower(opentype)] = specification
end
- local vc = v.context
- if vc then
- if type(vc) == "table" then
- for k=1,#vc do
- contexts[v] = vc[k]
+ local context = context
+ if context then
+ if type(context) == "table" then
+ for k=1,#context do
+ contexts[context[k]] = specification
end
else
- contexts[vc] = v
+ contexts[context] = specification
end
end
end
+local defaultvariant = variants["en-us"]
+
setmetatableindex(variants, function(t,k)
- str = lower(str)
- local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant.en).language
+ k = lower(k)
+ local v = (rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k) or defaultvariant).language
t[k] = v
return v
end)
setmetatableindex(opentypes, function(t,k)
- str = lower(str)
- local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant.en).opentype
+ k = lower(k)
+ local v = (rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k) or defaultvariant).opentype
t[k] = v
return v
end)
setmetatableindex(contexts, function(t,k)
- str = lower(str)
- local v = (l_variant[str] or l_opentype[str] or l_context[str] or l_variant[languages.default]).context
+ k = lower(str)
+ local v = (rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k) or defaultvariant).context
v = (type(v) == "table" and v[1]) or v
t[k] = v
return v
end)
setmetatableindex(records, function(t,k) -- how useful is this one?
- str = lower(str)
- local v = variants[str] or opentypes[str] or contexts[str] or variants.en
+ k = lower(k)
+ local v = rawget(variants,k) or rawget(opentypes,k) or rawget(contexts,k) or defaultvariant
t[k] = v
return v
end)
diff --git a/tex/context/base/lang-def.mkiv b/tex/context/base/lang-def.mkiv
index e838f60e1..d4e40dad1 100644
--- a/tex/context/base/lang-def.mkiv
+++ b/tex/context/base/lang-def.mkiv
@@ -211,28 +211,34 @@
\installlanguage
[\s!cs]
[\c!spacing=\v!packed,
- \c!leftsentence={\thickglue\endash\thickglue\penalty-20\relax},
- \c!rightsentence={\thickglue\endash\thickglue\penalty-20\relax},
- \c!leftsubsentence={\nobreakspace\emdash\nobreakspace\penalty-20\relax},
- \c!rightsubsentence={\nobreakspace\emdash\nobreakspace\penalty-20\relax},
+ \c!leftsentence={\nobreakspace\endash\thickglue\penalty\zerocount\relax},
+ \c!rightsentence=\c!leftsentence,
+ \c!leftsubsentence=\c!leftsentence,
+ \c!rightsubsentence=\c!rightsentence,
\c!leftquote=\lowerleftsingleninequote,
\c!rightquote=\upperrightsinglesixquote,
\c!leftquotation=\lowerleftdoubleninequote,
\c!rightquotation=\upperrightdoublesixquote,
- \c!date={\v!day,{.\thinspace},\v!month,\space,\v!year}]
+ \c!date={\v!day,\fourperemspace,\v!month,\space,\v!year}
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=3
+]
\installlanguage
[\s!sk]
[\c!spacing=\v!packed,
- \c!leftsentence=\emdash,
- \c!rightsentence=\emdash,
- \c!leftsubsentence=\emdash,
- \c!rightsubsentence=\emdash,
- \c!leftquote=\upperleftsinglesixquote,
- \c!rightquote=\upperrightsingleninequote,
- \c!leftquotation=\upperleftdoublesixquote,
- \c!rightquotation=\upperrightdoubleninequote,
- \c!date={\v!day,{.\thinspace},\v!month,\space,\v!year}]
+ \c!leftsentence={\nobreakspace\endash\thickglue\penalty\zerocount\relax},
+ \c!rightsentence=\c!leftsentence,
+ \c!leftsubsentence=\c!leftsentence,
+ \c!rightsubsentence=\c!rightsentence,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsinglesixquote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!date={\v!day,\fourperemspace,\v!month,\space,\v!year}
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=3
+]
\installlanguage
[\s!hr]
diff --git a/tex/context/base/lang-frd.mkiv b/tex/context/base/lang-frd.mkiv
new file mode 100644
index 000000000..716ff257d
--- /dev/null
+++ b/tex/context/base/lang-frd.mkiv
@@ -0,0 +1,141 @@
+%D \module
+%D [ file=lang-frd,
+%D version=2004.01.15,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Language Frequency Table Data,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is experimental work! Old stuff, whenever I need it I might
+%D do it in \LUA.
+
+% http://www.onzetaal.nl/advies/letterfreq.html
+
+\startcharactertable[nl]
+ \charfreq a 7.47
+ \charfreq b 1.58
+ \charfreq c 1.24
+ \charfreq d 5.93
+ \charfreq e 18.91
+ \charfreq f .81
+ \charfreq g 3.4
+ \charfreq h 2.38
+ \charfreq i 6.5
+ \charfreq j 1.46
+ \charfreq k 2.25
+ \charfreq l 3.57
+ \charfreq m 2.21
+ \charfreq n 10.03
+ \charfreq o 6.06
+ \charfreq p 1.57
+ \charfreq q .009
+ \charfreq r 6.41
+ \charfreq s 3.73
+ \charfreq t 6.79
+ \charfreq u 1.99
+ \charfreq v 2.85
+ \charfreq w 1.52
+ \charfreq x .04
+ \charfreq y .035
+ \charfreq z 1.39
+\stopcharactertable
+
+% http://caislab.icu.ac.kr/course/2001/spring/ice605/down/010306.pdf
+
+% \startcharactertable[en]
+% \charfreq a 8.2
+% \charfreq b 1.5
+% \charfreq c 2.8
+% \charfreq d 4.3
+% \charfreq e 12.7
+% \charfreq f 2.2
+% \charfreq g 2
+% \charfreq h 6.1
+% \charfreq i 7
+% \charfreq j .2
+% \charfreq k .8
+% \charfreq l 4
+% \charfreq m 2.4
+% \charfreq n 6.7
+% \charfreq o 7.5
+% \charfreq p 1.9
+% \charfreq q .1
+% \charfreq r 6
+% \charfreq s 6.3
+% \charfreq t 9.1
+% \charfreq u 2.8
+% \charfreq v 1
+% \charfreq w 2.3
+% \charfreq x .1
+% \charfreq y 2
+% \charfreq z .1
+% \stopcharactertable
+
+% http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm
+
+\startcharactertable[en]
+ \charfreq a 8.04
+ \charfreq b 1.54
+ \charfreq c 3.06
+ \charfreq d 3.99
+ \charfreq e 12.51
+ \charfreq f 2.3
+ \charfreq g 1.96
+ \charfreq h 5.49
+ \charfreq i 7.26
+ \charfreq j .16
+ \charfreq k .67
+ \charfreq l 4.14
+ \charfreq m 2.53
+ \charfreq n 7.09
+ \charfreq o 7.6
+ \charfreq p 2
+ \charfreq q .11
+ \charfreq r 6.12
+ \charfreq s 6.54
+ \charfreq t 9.25
+ \charfreq u 2.71
+ \charfreq v .99
+ \charfreq w 1.92
+ \charfreq x .19
+ \charfreq y 1.73
+ \charfreq z .09
+\stopcharactertable
+
+% http://www.blankenburg.de/gat/pages/fach/info/analyse2.htm
+
+\startcharactertable[de]
+ \charfreq a 6.47
+ \charfreq b 1.93
+ \charfreq c 2.68
+ \charfreq d 4.83
+ \charfreq e 17.48
+ \charfreq f 1.65
+ \charfreq g 3.06
+ \charfreq h 4.23
+ \charfreq i 7.73
+ \charfreq j .27
+ \charfreq k 1.46
+ \charfreq l 3.49
+ \charfreq m 2.58
+ \charfreq n 9.84
+ \charfreq o 2.98
+ \charfreq p .96
+ \charfreq q .02
+ \charfreq r 7.54
+ \charfreq s 6.83
+ \charfreq t 6.13
+ \charfreq u 4.17
+ \charfreq v .94
+ \charfreq w 1.48
+ \charfreq x .04
+ \charfreq y .08
+ \charfreq z 1.14
+\stopcharactertable
+
+\endinput
diff --git a/tex/context/base/lang-frq.mkiv b/tex/context/base/lang-frq.mkiv
new file mode 100644
index 000000000..24f535296
--- /dev/null
+++ b/tex/context/base/lang-frq.mkiv
@@ -0,0 +1,233 @@
+%D \module
+%D [ file=lang-frq,
+%D version=2004.01.15,
+%D title=\CONTEXT\ Language Macros,
+%D subtitle=Frequency 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 Language Macros / Frequency Tables}
+
+%D Some day I might redo this \LUA. But anyway, who uses it. It's rather
+%D old code.
+
+\unprotect
+
+%M \usemodule[layout]
+
+%D \macros
+%D {charwidthmethod}
+%D
+%D This module implements a method for determining the width of an
+%D average character in a language. It uses the dimensions of the
+%D current fonts.
+%D
+%D \def\ShwChrWd#1#2#3%
+%D {\chardef\charwidthmethod#1\relax
+%D \mainlanguage[#2#3]\the\dimexpr(\averagecharwidth)}
+%D
+%D \starttabulate[|c|c|c|c|c|c|]
+%D \HL
+%D \NC \NC\bf0=amount\NC\bf1=.5em\NC2=ex\NC\bf3=frequency\NC\bf4=list\NC\NR
+%D \HL
+%D \NC\bf en\NC\ShwChrWd0en\NC\ShwChrWd1en\NC\ShwChrWd2en\NC\ShwChrWd3en\NC\ShwChrWd4en\NC\NR
+%D \NC\bf nl\NC\ShwChrWd0nl\NC\ShwChrWd1nl\NC\ShwChrWd2nl\NC\ShwChrWd3nl\NC\ShwChrWd4nl\NC\NR
+%D \NC\bf de\NC\ShwChrWd0de\NC\ShwChrWd1de\NC\ShwChrWd2de\NC\ShwChrWd3de\NC\ShwChrWd4de\NC\NR
+%D \HL
+%D \stoptabulate
+%D
+%D Method~1 ignores the widths and assumes that each character has a
+%D width of .5em, which is true for most monospaced fonts. Method~2
+%D takes the x as starting point, and assumes that it's height kind of
+%D matches its width. Method~3 is the best one, and determines the
+%D average width based on the language specific character table.
+%D Method~4 is a mixture between the first two methods: character
+%D specific widths applied to an equal distribution. Method~0 reports
+%D the total count, which normally is~100.
+
+\chardef\charwidthmethod=3 % 0=amount 1=em 2=ex 3=frequency 4=flattened >4=ex
+
+%D \macros
+%D {charwidthlanguage}
+%D
+%D The language used for the calculations is defined as:
+
+\def\charwidthlanguage{\currentmainlanguage}
+
+%D \macros
+%D {charfreq}
+%D
+%D This method comes into action in the following macro:
+
+\def\charfreq#1 #2 % character fraction
+ {+(\ifcase\charwidthmethod
+ #2\dimexpr100\onepoint\relax
+ \or
+ #2\dimexpr\emwidth/2\relax
+ \or
+ #2\dimexpr\exheight\relax
+ \or
+ #2\fontcharwd\font`#1%
+ \or
+ \dimexpr100\fontcharwd\font`#1/\charactertsize\charwidthlanguage\relax % ugly hack
+ \else
+ #2\dimexpr\exheight\relax
+ \fi)}
+
+%D \macros
+%D {startcharactertable}
+%D
+%D A frequency table is defined with the following macro. The \type
+%D {charfreq} macro is used in this table.
+
+\installcorenamespace{frequencywidths}
+\installcorenamespace{frequencycounts}
+
+\let\stopcharactertable\relax
+
+\unexpanded\def\startcharactertable[#1]#2\stopcharactertable % \dimexpr has fuzzy lookahead
+ {\startnointerference
+ \setgvalue{\??frequencywidths#1}{#2}% the width vector
+ \scratchcounter\zerocount \def\charfreq##1 ##2 {\advance\scratchcounter\plusone} #2%
+ \setxvalue{\??frequencycounts#1}{\the\scratchcounter}% the character count
+ \stopnointerference}
+
+%D \macros
+%D {charactertable,charactertsize}
+%D
+%D The table content as well as the number of entries can be fetched with
+%D the following two macros. The architecture of the table and calling
+%D macro permits a fully expandable application.
+
+\def\charactertable#1%
+ {\csname\??frequencywidths\ifcsname\??frequencywidths#1\endcsname#1\else\s!en\fi\endcsname}
+
+\def\charactertsize#1%
+ {\csname\??frequencycounts\ifcsname\??frequencycounts#1\endcsname#1\else\s!en\fi\endcsname}
+
+%D Although it is of hardly any use, you can inherit a character table:
+%D
+%D \starttyping
+%D \startcharactertable[cz] \charactertable{en} \stopcharactertable
+%D \stoptyping
+
+\startcharactertable[en]
+ % empty
+\stopcharactertable % kind of default
+
+%D \macros
+%D {averagecharwidth}
+%D
+%D This macro reports the average width for the current main
+%D language (\the \dimexpr (\averagecharwidth)).
+
+\def\averagecharwidth{\dimexpr(\zeropoint\charactertable\charwidthlanguage)/100\relax}
+
+\unexpanded\def\showcharfreq
+ {\hbox\bgroup
+ \charwidthlanguage:%
+ \dostepwiserecurse\zerocount\plusfour\plusone
+ {\chardef\charwidthmethod\recurselevel\relax
+ \enspace\recurselevel/\the\dimexpr(\averagecharwidth)}%
+ \egroup}
+
+%D Just for fun, we show a few frequency tables as graphic (\in {figure}
+%D [fig:charfreq]).
+%D
+%D \startbuffer
+%D \definepalet [charfreq] [en=darkred, nl=darkgreen, de=darkblue]
+%D
+%D \def\charfreq#1 #2 %
+%D {\startMPdrawing
+%D interim linejoin := butt ;
+%D a := ASCII "#1" ;
+%D if (a >= (ASCII "a")) and (a <= (ASCII "z")) :
+%D draw ((0,#2*.25cm)--origin--(0,#2*.5cm))
+%D shifted (a*4mm+o,0)
+%D withpen pencircle scaled .5mm
+%D withcolor c;
+%D fi ;
+%D \stopMPdrawing}
+%D
+%D \resetMPdrawing
+%D \startMPdrawing
+%D numeric a, o ; a := o := 0 ;
+%D color c ; c := .5white ;
+%D string s ; s := "" ;
+%D \stopMPdrawing
+%D
+%D \startMPdrawing o := 0mm ; c := \MPcolor{charfreq:en} ; \stopMPdrawing
+%D \charactertable{en}
+%D
+%D \startMPdrawing o := 1mm ; c := \MPcolor{charfreq:nl} ; \stopMPdrawing
+%D \charactertable{nl}
+%D
+%D \startMPdrawing o := 2mm ; c := \MPcolor{charfreq:de} ; \stopMPdrawing
+%D \charactertable{de}
+%D
+%D \startMPdrawing
+%D for a := ASCII "a" upto ASCII "z" :
+%D draw textext.bot("\strut\tttf " & char a) shifted (a*4mm+1mm,-1mm) ;
+%D endfor ;
+%D \stopMPdrawing
+%D
+%D \MPdrawingdonetrue \getMPdrawing \resetMPdrawing
+%D \stopbuffer
+%D
+%D \placefigure
+%D [here]
+%D [fig:charfreq]
+%D {The character distributions for English, Dutch and German.}
+%D {\getbuffer}
+%D
+%D A few samples of usage of this mechanism are shown below:
+%D
+%D \startbuffer
+%D {\mainlanguage[en]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D {\mainlanguage[nl]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D {\mainlanguage[de]\hsize65\averagecharwidth\mainlanguage[en]\input ward \blank}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Although the widthts differ, the consequenes for breaking the paragraph
+%D into lines are minimal.
+
+%D \macros
+%D {freezeaveragecharacterwidth}
+%D
+%D This macro can be used to make sure that the width does not change during a
+%D page break when another font is used.
+
+\let\normalaveragecharacterwidth\averagecharacterwidth
+
+\unexpanded\def\freezeaveragecharacterwidth % global
+ {\xdef\averagecharacterwidth{\dimexpr\the\normalaveragecharacterwidth\relax}}
+
+%D Example:
+%D
+%D \starttyping
+%D \input lang-frq.mkiv
+%D \input lang-frd.mkiv
+%D
+%D \setupbodyfont
+%D [dejavu]
+%D
+%D \setemeasure{textwidth}{\the\dimexpr70\averagecharwidth}
+%D
+%D \setuplayout
+%D [width=\measure{textwidth}]
+%D
+%D \showframe
+%D
+%D \starttext
+%D \input ward
+%D \stoptext
+%D \stoptyping
+
+\protect \endinput
diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua
index 97528097f..eaedcd69a 100644
--- a/tex/context/base/lang-ini.lua
+++ b/tex/context/base/lang-ini.lua
@@ -29,12 +29,14 @@ local trace_patterns = false trackers.register("languages.patterns", function(v
local report_initialization = logs.reporter("languages","initialization")
-local prehyphenchar = lang.prehyphenchar -- global per language
+local prehyphenchar = lang.prehyphenchar -- global per language
local posthyphenchar = lang.posthyphenchar -- global per language
local lefthyphenmin = lang.lefthyphenmin
local righthyphenmin = lang.righthyphenmin
+local lang = lang
lang.exceptions = lang.hyphenation
+local new_langage = lang.new
languages = languages or {}
local languages = languages
@@ -65,7 +67,7 @@ local function resolve(tag)
if data then
instance = data.instance
if not instance then
- instance = lang.new(data.number)
+ instance = new_langage(data.number)
data.instance = instance
end
end
@@ -78,7 +80,7 @@ local function tolang(what) -- returns lang object
if data then
local instance = data.lang
if not instance then
- instance = lang.new(data.number)
+ instance = new_langage(data.number)
data.instance = instance
end
return instance
@@ -100,34 +102,34 @@ local function loaddefinitions(tag,specification)
local dataused, ok = data.used, false
for i=1,#definitions do
local definition = definitions[i]
- if definition ~= "" then
- if definition == "reset" then -- interfaces.variables.reset
+ if definition == "" then
+ -- error
+ elseif definition == "reset" then -- interfaces.variables.reset
+ if trace_patterns then
+ report_initialization("clearing patterns for language '%s'",tag)
+ end
+ instance:clear_patterns()
+ elseif not dataused[definition] then
+ dataused[definition] = definition
+ local filename = "lang-" .. definition .. ".lua"
+ local fullname = resolvers.findfile(filename) or ""
+ if fullname ~= "" then
if trace_patterns then
- report_initialization("clearing patterns for language '%s'",tag)
+ report_initialization("loading definition '%s' for language '%s' from '%s'",definition,tag,fullname)
end
- instance:clear_patterns()
- elseif not dataused[definition] then
- dataused[definition] = definition
- local filename = "lang-" .. definition .. ".lua"
- local fullname = resolvers.findfile(filename) or ""
- if fullname ~= "" then
- if trace_patterns then
- report_initialization("loading definition '%s' for language '%s' from '%s'",definition,tag,fullname)
- end
- local defs = dofile(fullname) -- use regular loader instead
- if defs then -- todo: version test
- ok, nofloaded = true, nofloaded + 1
- instance:patterns (defs.patterns and defs.patterns.data or "")
- instance:hyphenation(defs.exceptions and defs.exceptions.data or "")
- else
- report_initialization("invalid definition '%s' for language '%s' in '%s'",definition,tag,filename)
- end
- elseif trace_patterns then
+ local defs = dofile(fullname) -- use regular loader instead
+ if defs then -- todo: version test
+ ok, nofloaded = true, nofloaded + 1
+ instance:patterns (defs.patterns and defs.patterns .data or "")
+ instance:hyphenation(defs.exceptions and defs.exceptions.data or "")
+ else
report_initialization("invalid definition '%s' for language '%s' in '%s'",definition,tag,filename)
end
elseif trace_patterns then
- report_initialization("definition '%s' for language '%s' already loaded",definition,tag)
+ report_initialization("invalid definition '%s' for language '%s' in '%s'",definition,tag,filename)
end
+ elseif trace_patterns then
+ report_initialization("definition '%s' for language '%s' already loaded",definition,tag)
end
end
return ok
@@ -161,7 +163,7 @@ function languages.define(tag,parent)
storage.shared.noflanguages = noflanguages
end
-function languages.synonym(synonym,tag) -- convenience function
+function languages.setsynonym(synonym,tag) -- convenience function
local l = registered[tag]
if l then
l.synonyms[synonym] = true -- maybe some day more info
@@ -169,7 +171,7 @@ function languages.synonym(synonym,tag) -- convenience function
end
function languages.installed(separator)
- context(concat(sortedkeys(registered),separator or ","))
+ return concat(sortedkeys(registered),separator or ",")
end
function languages.current(n)
@@ -187,8 +189,6 @@ function languages.association(tag) -- not yet used
local lat = tag and associated[tag]
if lat then
return lat[1], lat[2]
- else
- return nil, nil
end
end
@@ -204,7 +204,7 @@ end
-- a bit messy, we will do all language setting in lua as we can now assign
-- and 'patterns' will go away here.
-function languages.setdirty(tag)
+function languages.unload(tag)
local l = registered[tag]
if l then
l.dirty = true
@@ -217,13 +217,9 @@ if environment.initex then
return 0
end
- function commands.languagenumber()
- context(0)
- end
-
else
- local function getnumber(tag,default,patterns)
+ function languages.getnumber(tag,default,patterns)
local l = registered[tag]
if l then
if l.dirty then
@@ -264,12 +260,6 @@ else
end
end
- languages.getnumber = getnumber
-
- function commands.languagenumber(tag,default,patterns)
- context(getnumber(tag,default,patterns))
- end
-
end
-- not that usefull, global values
@@ -294,7 +284,7 @@ function languages.loadwords(tag,filename)
end
end
-function languages.exceptions(tag,str)
+function languages.setexceptions(tag,str)
local data, instance = resolve(tag)
if data then
instance:hyphenation(string.strip(str)) -- we need to strip leading spaces
@@ -404,3 +394,20 @@ end)
--~ function hyphenation.loadexceptions(tag, exceptions)
--~ return loadthem(tag, exceptions, filterexceptions, "exceptions")
--~ end
+
+-- interface
+
+local getnumber = languages.getnumber
+
+function commands.languagenumber(tag,default,patterns)
+ context(getnumber(tag,default,patterns))
+end
+
+function commands.installedlanguages(separator)
+ context(languages.installed(separator))
+end
+
+commands.definelanguage = languages.define
+commands.setlanguagesynonym = languages.setsynonym
+commands.unloadlanguage = languages.unload
+commands.setlanguageexceptions = languages.setexceptions
diff --git a/tex/context/base/lang-ini.mkiv b/tex/context/base/lang-ini.mkiv
index 150b68f70..0b155cc74 100644
--- a/tex/context/base/lang-ini.mkiv
+++ b/tex/context/base/lang-ini.mkiv
@@ -174,7 +174,7 @@
\newtoks \everysetuplanguage
-\def\installedlanguages{\ctxlua{languages.installed()}}
+\def\installedlanguages{\ctxcommand{installedlanguages()}}
\unexpanded\def\doiflanguageelse#1%
{\ifcsname\??language#1\c!state\endcsname
@@ -199,10 +199,10 @@
\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")}%
+ \ctxcommand{definelanguage("#1","\specificlanguageparameter{#1}\s!default")}%
\the\everysetuplanguage}
{\setvalue{\??languagelinked#1}{#2}%
- \ctxlua{languages.synonym("#1","#2")}%
+ \ctxcommand{setlanguagesynonym("#1","#2")}%
\lang_basics_install_indeed{#1}{#2}}}
\def\lang_basics_install_indeed#1#2%
@@ -254,7 +254,7 @@
\lang_basics_synchronize}
\appendtoks
- \ctxlua{languages.setdirty("\currentsetuplanguage")}%
+ \ctxcommand{unloadlanguage("\currentsetuplanguage")}%
\to \everysetuplanguage
\setuplanguage
@@ -399,20 +399,27 @@
% we will also permit access by the other names
-\unexpanded\def\lang_basics_set_current[#1]%
- {\edef\askedlanguage{#1}%
- \ifx\askedlanguage\empty \else
+%D Fast switcher
+
+\def\lang_basics_switch_asked
+ {\ifx\askedlanguage\empty \else
\ifcsname\??languagelinked\askedlanguage\endcsname
\edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
\ifx\currentlanguage\askedlanguage \else
\setcurrentlanguage\currentmainlanguage\askedlanguage
\lang_basics_synchronize
\fi
- \else
- \showmessage\m!languages6{#1}%
\fi
\fi}
+\unexpanded\def\uselanguageparameter#1%
+ {\edef\askedlanguage{#1\c!language}%
+ \lang_basics_switch_asked}
+
+\unexpanded\def\lang_basics_set_current[#1]%
+ {\edef\askedlanguage{#1}%
+ \lang_basics_switch_asked}
+
\unexpanded\def\language
{\doifnextoptionalelse\lang_basics_set_current\normallanguage}
@@ -570,15 +577,15 @@
\let\stopexceptions\relax
\unexpanded\def\startexceptions
- {\dosingleempty\dostartexceptions}
+ {\dosingleempty\lang_basics_start_exceptions}
-\def\dostartexceptions[#1]#2\stopexceptions % multilingual or not?
+\def\lang_basics_start_exceptions[#1]#2\stopexceptions % multilingual or not?
{\begingroup
\edef\askedlanguage{\reallanguagetag{#1}}%
\ifx\askedlanguage\empty
\let\askedlanguage\currentlanguage
\fi
- \ctxlua{languages.exceptions("\askedlanguage",\!!bs#2\!!es)}%
+ \ctxcommand{setlanguageexceptions("\askedlanguage",\!!bs#2\!!es)}%
\endgroup}
%D For the moment here:
diff --git a/tex/context/base/lang-lab.lua b/tex/context/base/lang-lab.lua
index 360f2aa11..8d48a4988 100644
--- a/tex/context/base/lang-lab.lua
+++ b/tex/context/base/lang-lab.lua
@@ -61,15 +61,20 @@ if not modules then modules = { } end modules ['lang-lab'] = {
local format, find = string.format, string.find
local next, rawget, type = next, rawget, type
-local prtcatcodes = tex.prtcatcodes
local lpegmatch = lpeg.match
-languages.labels = languages.labels or { }
+local prtcatcodes = catcodes.numbers.prtcatcodes -- todo: use different method
local trace_labels = false trackers.register("languages.labels", function(v) trace_labels = v end)
local report_labels = logs.reporter("languages","labels")
-local variables = interfaces.variables
+-- trace_labels = true
+
+languages.labels = languages.labels or { }
+local labels = languages.labels
+
+local variables = interfaces.variables
+local settings_to_array = utilities.parsers.settings_to_array
local splitter = lpeg.splitat(":")
@@ -77,19 +82,21 @@ local function split(tag)
return lpegmatch(splitter,tag)
end
-languages.labels.split = split
+labels.split = split
+
+local contextsprint = context.sprint
-local function definelanguagelabels(data,command,tag,rawtag)
+local function definelanguagelabels(data,class,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])
+ contextsprint(prtcatcodes,"\\setlabeltextpair{",class,"}{",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)
+ contextsprint(prtcatcodes,"\\setlabeltextpair{",class,"}{",language,"}{",tag,"}{",text,"}{}")
if trace_labels then
report_labels("language '%s', defining label '%s' as '%s'",language,rawtag,text)
end
@@ -97,11 +104,10 @@ local function definelanguagelabels(data,command,tag,rawtag)
end
end
-function languages.labels.define(command,name,prefixed)
+function labels.define(class,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
@@ -110,31 +116,30 @@ function languages.labels.define(command,name,prefixed)
if second then
if rawget(variables,first) then
if rawget(variables,second) then
- definelanguagelabels(data,command,format("\\v!%s:\\v!%s",first,second),tag)
+ definelanguagelabels(data,class,format("\\v!%s:\\v!%s",first,second),tag)
else
- definelanguagelabels(data,command,format("\\v!%s:%s",first,second),tag)
+ definelanguagelabels(data,class,format("\\v!%s:%s",first,second),tag)
end
elseif rawget(variables,second) then
- definelanguagelabels(data,command,format("%s:\\v!%s",first,second),tag)
+ definelanguagelabels(data,class,format("%s:\\v!%s",first,second),tag)
else
- definelanguagelabels(data,command,format("%s:%s",first,second),tag)
+ definelanguagelabels(data,class,format("%s:%s",first,second),tag)
end
elseif rawget(variables,rawtag) then
- definelanguagelabels(data,command,format("\\v!%s",tag),tag)
+ definelanguagelabels(data,class,format("\\v!%s",tag),tag)
else
- definelanguagelabels(data,command,tag,tag)
+ definelanguagelabels(data,class,tag,tag)
end
else
- definelanguagelabels(data,command,tag,tag)
+ definelanguagelabels(data,class,tag,tag)
end
end
- context.popcatcodes() -- context.protect
else
report_labels("unknown label set '%s'",name)
end
end
---~ function languages.labels.check()
+--~ function labels.check()
--~ for category, list in next, languages.data.labels do
--~ for tag, specification in next, list do
--~ for language, text in next, specification.labels do
@@ -147,8 +152,32 @@ end
--~ end
--~ end
--~
---~ languages.labels.check()
+--~ labels.check()
+
+
+-- interface
+
+commands.definelabels = labels.define
-- function commands.setstrippedtextprefix(str)
-- context(string.strip(str))
-- end
+
+function commands.concatcommalist(settings) -- it's too easy to forget that this one is there
+ local list = settings_to_array(settings.text or "")
+ local size = #list
+ if size > 1 then
+ local set = settings_to_array(settings.separators or "")
+ local one = set[1] or settings.first or " "
+ local two = set[2] or settings.second or " "
+ context(list[1])
+ for i=2,size-1 do
+ context(one)
+ context(list[i])
+ end
+ context(two)
+ end
+ if size > 0 then
+ context(list[size])
+ end
+end
diff --git a/tex/context/base/lang-lab.mkiv b/tex/context/base/lang-lab.mkiv
index a9744f699..c3c584beb 100644
--- a/tex/context/base/lang-lab.mkiv
+++ b/tex/context/base/lang-lab.mkiv
@@ -37,8 +37,6 @@
%D in front as well as after a part number. This is why the
%D current implementation of labels supports two labels too.
-\ifdefined\simplifiedcommands \else \newtoks\simplifiedcommands \fi
-
%D \macros
%D {setupheadtext, setuplabeltext}
%D
@@ -135,8 +133,7 @@
\let#7\firstofoneargument % to be checked
\let#8\firstofoneargument % to be checked
\let#9\firstofoneargument % to be checked
- \to \simplifiedcommands
- }
+ \to \everysimplifycommands}
\let\flushleftlabelclass \firstoftwoarguments
\let\flushrightlabelclass\secondoftwoarguments
@@ -234,17 +231,18 @@
\def\lang_labels_text_prefix_assign_dumb#1[#2,#3]%
{\expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}}
+\unexpanded\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end
+ {\expandafter\def\csname\??label#1:\reallanguagetag{#2}:#3\endcsname{{#4}{#5}}} % class tag key left right
+
\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)%
-}
+\ctxcommand{definelabels("head", "titles", true )}
+\ctxcommand{definelabels("label", "texts", true )}
+\ctxcommand{definelabels("mathlabel", "functions",false)}
+\ctxcommand{definelabels("taglabel", "tags", false)}
%D \macros
%D {translate}
@@ -264,15 +262,17 @@
%D which expands to {\em something} or {\em iets}, depending on
%D de current language.
+\installcorenamespace{translation}
+
\unexpanded\def\translate
{\dosingleempty\lang_translate}
\def\lang_translate[#1]%
- {\getparameters[\??lg][#1]%
- \ifcsname\??lg\currentlanguage\endcsname
- \csname\??lg\currentlanguage\endcsname
- \else\ifcsname\??lg\s!en\endcsname
- \csname\??lg\s!en\endcsname
+ {\getparameters[\??translation][#1]%
+ \ifcsname\??translation\currentlanguage\endcsname
+ \csname\??translation\currentlanguage\endcsname
+ \else\ifcsname\??translation\s!en\endcsname
+ \csname\??translation\s!en\endcsname
\else
[translation #1]%
\fi\fi}
@@ -295,7 +295,43 @@
%D \stoptyping
\def\assigntranslation[#1]\to#2%
- {\getparameters[\??lg][#1]%
- \edef#2{\csname\??lg\currentlanguage\endcsname}}
+ {\getparameters[\??translation][#1]%
+ \edef#2{\csname\??translation\currentlanguage\endcsname}}
+
+%D \macros
+%D {commalistsentence}
+%D
+%D Redone in \LUA:
+%D
+%D \startbuffer
+%D \commalistsentence[aap,noot,mies]
+%D \commalistsentence[aap,noot]
+%D \commalistsentence[aap]
+%D \commalistsentence[a,b,c]
+%D \commalistsentence[a,b,c][{ \& },{ and }]
+%D \commalistsentence[a,b,c][+,-]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\unexpanded\def\commalistsentence
+ {\dodoubleempty\typo_helpers_concat_comma_list}
+
+\def\typo_helpers_concat_comma_list[#1][#2]%
+ {\ctxcommand{concatcommalist{
+ text = \!!bs#1\!!es,
+ separators = \!!bs#2\!!es,
+ first = \!!bs\labeltext{and-1}\!!es,
+ second = \!!bs\labeltext{and-2}\!!es
+ }}}
+
+\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
\protect \endinput
diff --git a/tex/context/base/lang-mis.mkiv b/tex/context/base/lang-mis.mkiv
index ce23c0f60..4d8b8e08a 100644
--- a/tex/context/base/lang-mis.mkiv
+++ b/tex/context/base/lang-mis.mkiv
@@ -664,4 +664,35 @@
\ifdefined\normalcompound \else \let\normalcompound=| \fi
+%D \macros
+%D {compound}
+%D
+%D We will overload the already active \type {|} so we have
+%D to save its meaning in order to be able to use this handy
+%D macro.
+%D
+%D \starttyping
+%D so test\compound{}test can be used instead of test||test
+%D \stoptyping
+
+\bgroup
+
+ \catcode\barasciicode\activecatcode
+
+ \unexpanded\gdef\compound#1{|#1|}
+
+ \doglobal \appendtoks
+ \def|#1|{\ifx#1\empty\empty-\else#1\fi}%
+ \to \everysimplifycommands
+
+\egroup
+
+%D Here we hook some code into the clean up mechanism needed
+%D for verbatim data.
+
+\appendtoks
+ \disablecompoundcharacters
+ \disablediscretionaries
+\to \everycleanupfeatures
+
\protect \endinput
diff --git a/tex/context/base/lang-txt.lua b/tex/context/base/lang-txt.lua
index f28cb18f1..7b0e046fe 100644
--- a/tex/context/base/lang-txt.lua
+++ b/tex/context/base/lang-txt.lua
@@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['lang-txt'] = {
comment = "companion to lang-lab.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+ license = "see context related readme files",
+ dataonly = true,
}
-- The content of this file is derived from the mkii lang-* files and
@@ -65,229 +66,311 @@ data.labels={
functions={
Pr={
labels={
+ cz="P",
en="Pr",
+ sk="P",
},
},
arccos={
labels={
+ cz="arccos",
en="arccos",
hr="arc\\sixperemspace cos",
pl="arc\\sixperemspace cos",
+ sk="arccos",
},
},
arcctg={
labels={
+ cz="arccotg",
en="arccot",
hr="arc\\sixperemspace ctg",
pl="arc\\sixperemspace ctg",
+ sk="arccotg",
},
},
arcsin={
labels={
+ cz="arcsin",
en="arcsin",
hr="arc\\sixperemspace sin",
pl="arc\\sixperemspace sin",
+ sk="arcsin",
},
},
arctan={
labels={
+ cz="arctg",
en="arctan",
hr="arc\\sixperemspace tg",
pl="arc\\sixperemspace tg",
+ sk="arctg",
},
},
arctg={
labels={
+ cz="arctg",
en="arctan",
hr="arc\\sixperemspace tg",
pl="arc\\sixperemspace tg",
+ sk="arctg",
},
},
arg={
labels={
+ cz="arg",
en="arg",
+ sk="arg",
},
},
cos={
labels={
+ cz="cos",
en="cos",
+ sk="cos",
},
},
cosh={
labels={
+ cz="cosh",
en="cosh",
+ sk="cosh",
},
},
cot={
labels={
+ cz="cotg",
en="cot",
hr="ctg",
pl="ctg",
+ sk="cotg",
},
},
coth={
labels={
+ cz="cotgh",
en="coth",
+ sk="cotgh",
},
},
csc={
labels={
+ cz="cosec",
en="csc",
+ sk="cosec",
},
},
ctg={
labels={
+ cz="cotg",
en="cot",
hr="ctg",
pl="ctg",
+ sk="cotg",
},
},
deg={
labels={
+ cz="deg",
en="deg",
+ sk="deg",
},
},
det={
labels={
+ cz="det",
en="det",
+ sk="det",
},
},
dim={
labels={
+ cz="dim",
en="dim",
+ sk="dim",
},
},
exp={
labels={
+ cz="exp",
en="exp",
+ sk="exp",
},
},
gcd={
labels={
+ cz="NSD",
en="gcd",
hr="nzd",
nl="ggd",
+ sk="NSD",
},
},
hom={
labels={
+ cz="Hom",
en="hom",
+ sk="Hom",
},
},
inf={
labels={
+ cz="inf",
en="inf",
+ sk="inf",
},
},
injlim={
labels={
+ cz="inj\\sixperemspace lim",
en="inj\\sixperemspace lim",
+ sk="inj\\sixperemspace lim",
},
},
ker={
labels={
+ cz="ker",
en="ker",
+ sk="ker",
},
},
lcm={
labels={
+ cz="NSN",
en="lcm",
hr="nzv",
nl="kgv",
+ sk="NSN",
},
},
lg={
labels={
+ cz="log",
en="lg",
+ sk="log",
},
},
lim={
labels={
+ cz="lim",
en="lim",
+ sk="lim",
},
},
liminf={
labels={
+ cz="lim\\sixperemspace inf",
en="lim\\sixperemspace inf",
+ sk="lim\\sixperemspace inf",
},
},
limsup={
labels={
+ cz="lim\\sixperemspace sup",
en="lim\\sixperemspace sup",
+ sk="lim\\sixperemspace sup",
},
},
ln={
labels={
+ cz="ln",
en="ln",
+ sk="ln",
},
},
log={
labels={
+ cz="log",
en="log",
+ sk="log",
},
},
max={
labels={
+ cz="max",
en="max",
+ sk="max",
},
},
median={
labels={
+ cz="\\tilde",
en="median",
+ sk="\\tilde",
},
},
min={
labels={
+ cz="min",
en="min",
+ sk="min",
},
},
mod={
labels={
+ cz="mod",
en="mod",
+ sk="mod",
},
},
projlim={
labels={
+ cz="proj\\sixperemspace lim",
en="proj\\sixperemspace lim",
+ sk="proj\\sixperemspace lim",
},
},
sec={
labels={
+ cz="sec",
en="sec",
+ sk="sec",
},
},
sin={
labels={
+ cz="sin",
en="sin",
+ sk="sin",
},
},
sinh={
labels={
+ cz="sinh",
en="sinh",
+ sk="sinh",
},
},
sup={
labels={
+ cz="sup",
en="sup",
+ sk="sup",
},
},
tan={
labels={
+ cz="tg",
en="tan",
hr="tg",
pl="tg",
+ sk="tg",
},
},
tanh={
labels={
+ cz="tgh",
en="tanh",
+ sk="tgh",
},
},
tg={
labels={
+ cz="tg",
en="tan",
hr="tg",
pl="tg",
+ sk="tg",
},
},
},
@@ -296,7 +379,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="a",
da="",
de="und",
en="and",
@@ -316,7 +399,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="a",
sl="",
sv="",
tk="",
@@ -403,10 +486,10 @@ data.labels={
},
},
["april:mnem"]={
- labels={
+ labels={
af="",
ca="",
- cs="",
+ cs="dub.",
da="",
de="",
en="apr",
@@ -426,7 +509,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="apr.",
sl="",
sv="",
tk="",
@@ -460,7 +543,7 @@ data.labels={
pt="",
ro="",
ru="на странице ",
- sk="",
+ sk="na strane ",
sl="na strani ",
sv="på sida ",
tk="",
@@ -513,7 +596,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="srp.",
da="",
de="",
en="aug",
@@ -533,7 +616,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="aug.",
sl="",
sv="",
tk="",
@@ -584,7 +667,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs=" (pokračování)",
da="",
de="",
en=" (continued)",
@@ -604,7 +687,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk=" (pokračovanie)",
sl="",
sv="",
tk="",
@@ -656,7 +739,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="pros.",
da="",
de="",
en="dec",
@@ -676,7 +759,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="dec.",
sl="",
sv="",
tk="",
@@ -728,7 +811,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="ún.",
da="",
de="",
en="feb",
@@ -748,7 +831,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="feb.",
sl="",
sv="",
tk="",
@@ -822,7 +905,7 @@ data.labels={
pt="sexta-feira",
ro="vineri",
ru="пятница",
- sk="",
+ sk="piatok",
sl="petek",
sv="fredag",
tk="bäşinji gün",
@@ -893,7 +976,7 @@ data.labels={
pt="",
ro="",
ru="см. выше",
- sk="",
+ sk="pozri hore",
sl="glej zgoraj",
sv="se ovan",
tk="",
@@ -927,7 +1010,7 @@ data.labels={
pt="",
ro="",
ru="см. ниже",
- sk="",
+ sk="pozri ďalej",
sl="glej spodaj",
sv="se nedan",
tk="",
@@ -1016,7 +1099,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="led.",
da="",
de="",
en="jan",
@@ -1036,7 +1119,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="jan.",
sl="",
sv="",
tk="",
@@ -1089,7 +1172,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="čce",
da="",
de="",
en="jul",
@@ -1109,7 +1192,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="júla",
sl="",
sv="",
tk="",
@@ -1161,7 +1244,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="čer.",
da="",
de="",
en="jun",
@@ -1181,7 +1264,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="júna",
sl="",
sv="",
tk="",
@@ -1306,7 +1389,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="břez.",
da="",
de="",
en="mar",
@@ -1326,7 +1409,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="mar.",
sl="",
sv="",
tk="",
@@ -1379,7 +1462,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="květ.",
da="",
de="",
en="may",
@@ -1399,7 +1482,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="mája",
sl="",
sv="",
tk="",
@@ -1436,7 +1519,7 @@ data.labels={
pt="segunda-feira",
ro="luni",
ru="понедельник",
- sk="",
+ sk="pondelok",
sl="ponedeljek",
sv="måndag",
tk="birinji gün",
@@ -1488,7 +1571,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="list.",
da="",
de="",
en="nov",
@@ -1508,7 +1591,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="nov.",
sl="",
sv="",
tk="",
@@ -1559,7 +1642,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="říj.",
da="",
de="",
en="oct",
@@ -1579,7 +1662,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="okt.",
sl="",
sv="",
tk="",
@@ -1614,7 +1697,7 @@ data.labels={
pt="",
ro="",
ru="страница ",
- sk="",
+ sk="strana ",
sl="stran ",
sv="Sida ",
tk="",
@@ -1647,7 +1730,7 @@ data.labels={
nb="Del",
nl="Deel ",
nn="Del",
- pl="Część ",
+ pl="Część ",
pt="Parte ",
ro="Partea ",
ru="Часть ",
@@ -1688,7 +1771,7 @@ data.labels={
pt="sábado",
ro="sâmbătă",
ru="суббота",
- sk="",
+ sk="sobota",
sl="sobota",
sv="lördag",
tk="altynjy gün",
@@ -1761,7 +1844,7 @@ data.labels={
pt="",
ro="",
ru="см. ",
- sk="",
+ sk="pozri ",
sl="glej ",
sv="se ",
tk="",
@@ -1813,7 +1896,7 @@ data.labels={
labels={
af="",
ca="",
- cs="",
+ cs="září",
da="",
de="",
en="sep",
@@ -1833,7 +1916,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="sept.",
sl="",
sv="",
tk="",
@@ -1981,7 +2064,7 @@ data.labels={
pt="domingo",
ro="duminică",
ru="воскресенье",
- sk="",
+ sk="nedeľa",
sl="nedelja",
sv="söndag",
tk="dynç gün",
@@ -2055,7 +2138,7 @@ data.labels={
pt="quinta-feira",
ro="joi",
ru="четверг",
- sk="",
+ sk="štvrtok",
sl="četrtek",
sv="torsdag",
tk="dördünji gün",
@@ -2092,7 +2175,7 @@ data.labels={
pt="terça-feira",
ro="marți",
ru="вторник",
- sk="",
+ sk="utorok",
sl="torek",
sv="tisdag",
tk="ikinji gün",
@@ -2129,7 +2212,7 @@ data.labels={
pt="quarta-feira",
ro="miercuri",
ru="среда",
- sk="",
+ sk="streda",
sl="sreda",
sv="onsdag",
tk="üçünji",
@@ -2220,7 +2303,7 @@ data.labels={
ar="الأشكال",
ca="Figures",
cn="图形",
- cs="Obrázky",
+ cs="Seznam obrázků",
da="Figurer",
de="Abbildungen",
en="Figures",
@@ -2242,7 +2325,7 @@ data.labels={
pt="Figuras",
ro="Figuri",
ru="Список иллюстраций",
- sk="Obrázkov",
+ sk="Zoznam obrázkov",
sl="Slike",
sv="Figurer",
tk="Suratlar",
@@ -2257,7 +2340,7 @@ data.labels={
ar="الرسوم",
ca="Gràfiques",
cn="图",
- cs="Grafy",
+ cs="Seznam grafů",
da="Grafik",
de="Graphiken",
en="Graphics",
@@ -2279,7 +2362,7 @@ data.labels={
pt="Gráficos",
ro="Grafice",
ru="Список графиков",
- sk="Graf",
+ sk="Zoznam grafov",
sl="Slike",
sv="Grafik",
tk="Grafikler",
@@ -2423,7 +2506,7 @@ data.labels={
pt="",
ro="",
ru="",
- sk="",
+ sk="Literatúra",
sl="Literatura",
sv="",
tk="",
@@ -2438,7 +2521,7 @@ data.labels={
ar="الجداول",
ca="Taules",
cn="表格",
- cs="Tabulky",
+ cs="Seznam tabulek",
da="Tabeller",
de="Tabellen",
en="Tables",
@@ -2460,7 +2543,7 @@ data.labels={
pt="Tabelas",
ro="Tabele",
ru="Список таблиц",
- sk="Tabuliek",
+ sk="Zoznam tabuliek",
sl="Tabele",
sv="Tabeller",
tk="Tablisalar",
diff --git a/tex/context/base/lang-url.lua b/tex/context/base/lang-url.lua
index 09a4e5d90..3b354216a 100644
--- a/tex/context/base/lang-url.lua
+++ b/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, utfchar, utfgsub = utf.byte, utf.char, utf.gsub
+local utfbyte, utfchar = utf.byte, utf.char
context = context
@@ -63,7 +63,7 @@ local characters = utilities.storage.allocate {
}
local mapping = utilities.storage.allocate {
---~ [utfchar(0xA0)] = "~", -- nbsp (catch)
+ -- [utfchar(0xA0)] = "~", -- nbsp (catch)
}
hyphenatedurl.characters = characters
@@ -72,7 +72,8 @@ hyphenatedurl.lefthyphenmin = 2
hyphenatedurl.righthyphenmin = 3
hyphenatedurl.discretionary = nil
--- more fun is to write nodes
+-- more fun is to write nodes .. maybe it's nicer to do this
+-- in an attribute handler anyway
local function action(hyphenatedurl,str,left,right,disc)
local n = 0
diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua
index 3d3cb6aec..c5bc75ca2 100644
--- a/tex/context/base/lang-wrd.lua
+++ b/tex/context/base/lang-wrd.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['lang-ini'] = {
+if not modules then modules = { } end modules ['lang-wrd'] = {
version = 1.001,
comment = "companion to lang-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -90,76 +90,11 @@ function words.found(id, str)
end
end
--- The following code is an adaption of experimental code for
--- hyphenating and spell checking.
+-- The following code is an adaption of experimental code for hyphenating and
+-- spell checking.
-- there is an n=1 problem somewhere in nested boxes
---~ local function mark_words(head,whenfound) -- can be optimized and shared
---~ local current, start, str, language, n, done = head, nil, "", nil, 0, false
---~ local function action()
---~ if #str > 0 then
---~ local f = whenfound(language,str)
---~ if f then
---~ done = true
---~ for i=1,n do
---~ f(start)
---~ start = start.next
---~ end
---~ end
---~ end
---~ str, start, n = "", nil, 0
---~ end
---~ while current do
---~ local id = current.id
---~ if id == glyph_code then
---~ local a = current.lang
---~ if a then
---~ if a ~= language then
---~ if start then
---~ action()
---~ end
---~ language = a
---~ end
---~ elseif start then
---~ action()
---~ language = a
---~ end
---~ local components = current.components
---~ if components then
---~ start = start or current
---~ n = n + 1
---~ for g in traverse_nodes(components) do
---~ str = str .. utfchar(g.char)
---~ end
---~ else
---~ local code = current.char
---~ local data = chardata[code]
---~ if is_letter[data.category] then
---~ start = start or current
---~ n = n + 1
---~ str = str .. utfchar(code) -- slow, maybe str should be a table (and given max)
---~ elseif start then
---~ action()
---~ end
---~ end
---~ elseif id == disc_code then
---~ if n > 0 then
---~ n = n + 1
---~ end
---~ elseif id == kern_code and current.subtype == kerning_code and start then
---~ -- ok
---~ elseif start then
---~ action()
---~ end
---~ current = current.next
---~ end
---~ if start then
---~ action()
---~ end
---~ return head, done
---~ end
-
local function mark_words(head,whenfound) -- can be optimized and shared
local current, language, done = head, nil, nil, 0, false
local str, s, nds, n = { }, 0, { }, 0 -- n could also be a table, saves calls
@@ -263,21 +198,19 @@ end
local cache = { } -- can also be done with method 1 -- frozen colors once used
-setmetatable(cache, {
- __index = function(t,k) -- k == language, numbers[k] == tag
- local c
- if type(k) == "string" then
- c = colist[k]
- elseif k < 0 then
- c = colist["word:unset"]
- else
- c = colist["word:" .. (numbers[k] or "unset")] or colist["word:unknown"]
- end
- local v = c and function(n) set_attribute(n,a_color,c) end or false
- t[k] = v
- return v
+table.setmetatableindex(cache, function(t,k) -- k == language, numbers[k] == tag
+ local c
+ if type(k) == "string" then
+ c = colist[k]
+ elseif k < 0 then
+ c = colist["word:unset"]
+ else
+ c = colist["word:" .. (numbers[k] or "unset")] or colist["word:unknown"]
end
-} )
+ local v = c and function(n) set_attribute(n,a_color,c) end or false
+ t[k] = v
+ return v
+end)
-- method 1
diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua
index 154296e9b..aee2c4edf 100644
--- a/tex/context/base/lpdf-ano.lua
+++ b/tex/context/base/lpdf-ano.lua
@@ -325,7 +325,7 @@ function nodeinjections.destination(width,height,depth,name,view)
if trace_destinations then
report_destination("w=%s, h=%s, d=%s, n=%s, v=%s",width,height,depth,name,view or "no view")
end
- return pdfdestination_node(width,height,depth,name,view)
+ return pdfdestination_node(width,height,depth,name,view) -- can be begin/end node
end
end
@@ -607,8 +607,8 @@ function executers.submitform(arguments)
local flag = flags[formmethod] or flags.post
flag = (flag and (flag[formformat] or flag.xml)) or 32 -- default: post, xml
return pdfdictionary {
- S = pdfconstant("ResetForm"),
- F = fieldset(arguments[1]),
+ S = pdfconstant("SubmitForm"),
+ F = arguments[1],
Field = fieldset(arguments[2]),
Flags = flag,
-- \PDFsubmitfiller
diff --git a/tex/context/base/lpdf-col.lua b/tex/context/base/lpdf-col.lua
index 0c2a49ebe..db9d3268b 100644
--- a/tex/context/base/lpdf-col.lua
+++ b/tex/context/base/lpdf-col.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['lpdf-mis'] = {
+if not modules then modules = { } end modules ['lpdf-col'] = {
version = 1.001,
comment = "companion to lpdf-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -13,6 +13,8 @@ local round = math.round
local backends, lpdf, nodes = backends, lpdf, nodes
+local allocate = utilities.storage.allocate
+
local nodeinjections = backends.pdf.nodeinjections
local codeinjections = backends.pdf.codeinjections
local registrations = backends.pdf.registrations
@@ -44,7 +46,7 @@ local report_color = logs.reporter("colors","backend")
-- page groups (might move to lpdf-ini.lua)
-local colorspaceconstants = { -- v_none is ignored
+local colorspaceconstants = allocate { -- v_none is ignored
gray = pdfconstant("DeviceGray"),
rgb = pdfconstant("DeviceRGB"),
cmyk = pdfconstant("DeviceCMYK"),
@@ -694,7 +696,7 @@ end
-- this will move to lpdf-spe.lua
-backends.pdf.tables.vfspecials = { -- todo: distinguish between glyph and rule color
+backends.pdf.tables.vfspecials = allocate { -- todo: distinguish between glyph and rule color
red = { "special", 'pdf: 1 0 0 rg 1 0 0 RG' },
green = { "special", 'pdf: 0 1 0 rg 0 1 0 RG' },
diff --git a/tex/context/base/lpdf-epa.lua b/tex/context/base/lpdf-epa.lua
index c8d23a618..03a36f2dc 100644
--- a/tex/context/base/lpdf-epa.lua
+++ b/tex/context/base/lpdf-epa.lua
@@ -111,9 +111,9 @@ function codeinjections.mergereferences(specification)
local size = specification.size or "crop" -- todo
local pagedata = document.pages[pagenumber]
local annotations = pagedata.Annots
- local namespace = format("lpdf-epa-%s-",file.removesuffix(file.basename(fullname)))
- local reference = namespace .. pagenumber
- if annotations.n > 0 then
+ if annotations and annotations.n > 0 then
+ local namespace = format("lpdf-epa-%s-",file.removesuffix(file.basename(fullname)))
+ local reference = namespace .. pagenumber
local mediabox = pagedata.MediaBox
local llx, lly, urx, ury = mediabox[1], mediabox[2], mediabox[3], mediabox[4]
local width, height = xscale * (urx - llx), yscale * (ury - lly) -- \\overlaywidth, \\overlayheight
diff --git a/tex/context/base/lpdf-epd.lua b/tex/context/base/lpdf-epd.lua
index 76d258cef..1c4b4b5c5 100644
--- a/tex/context/base/lpdf-epd.lua
+++ b/tex/context/base/lpdf-epd.lua
@@ -179,14 +179,17 @@ checked_access = {
ref = function(v)
return v:getRef()
end,
+ null = function()
+ return nil
+ end,
}
---~ checked_access.real = epdf.real
---~ checked_access.integer = epdf.integer
---~ checked_access.string = epdf.string
---~ checked_access.boolean = epdf.boolean
---~ checked_access.name = epdf.name
---~ checked_access.ref = epdf.ref
+-- checked_access.real = epdf.real
+-- checked_access.integer = epdf.integer
+-- checked_access.string = epdf.string
+-- checked_access.boolean = epdf.boolean
+-- checked_access.name = epdf.name
+-- checked_access.ref = epdf.ref
local function getnames(document,n,target) -- direct
if n then
@@ -323,6 +326,15 @@ function lpdf.epdf.load(filename)
return document
end
+-- for k, v in next, expand(t) do
+
+function lpdf.epdf.expand(t)
+ if type(t) == "table" then
+ local dummy = t.dummy
+ end
+ return t
+end
+
-- helpers
-- function lpdf.epdf.getdestinationpage(document,name)
diff --git a/tex/context/base/lpdf-fmt.lua b/tex/context/base/lpdf-fmt.lua
index 8e118db12..859a489ef 100644
--- a/tex/context/base/lpdf-fmt.lua
+++ b/tex/context/base/lpdf-fmt.lua
@@ -36,6 +36,8 @@ local pdfstring = lpdf.string
local pdfverbose = lpdf.verbose
local pdfflushstreamfileobject = lpdf.flushstreamfileobject
+local texset = tex.set -- we could make tex.setglobal
+
local addtoinfo = lpdf.addtoinfo
local injectxmpinfo = lpdf.injectxmpinfo
local insertxmpinfo = lpdf.insertxmpinfo
@@ -360,7 +362,7 @@ local function loadprofile(name,filename)
for i=1,#databases do
local filename = locatefile(databases[i])
if filename and filename ~= "" then
- local suffix = file.extname(filename)
+ local suffix = file.suffix(filename)
local lname = lower(name)
if suffix == "xml" then
local xmldata = xml.load(filename) -- no need for caching it
@@ -625,15 +627,17 @@ end
lpdf.registerdocumentfinalizer(flushoutputintents,2,"output intents")
function codeinjections.setformat(s)
- local format, level, profile, intent, option, filename =
- s.format or "", s.level or "", s.profile or "", s.intent or "", s.option or "", s.file or ""
- if format == "" then
- -- we ignore this as we hook it in \everysetupbackend
- else
+ local format = s.format or ""
+ local level = tonumber(s.level)
+ local intent = s.intent or ""
+ local profile = s.profile or ""
+ local option = s.option or ""
+ local filename = s.file or ""
+ if format ~= "" then
local spec = formats[lower(format)]
if spec then
- formatspecification, formatname = spec, spec.format_name
- level = level and tonumber(level)
+ formatspecification = spec
+ formatname = spec.format_name
report_backend("setting format to '%s'",formatname)
local xmp_file = formatspecification.xmp_file or ""
if xmp_file == "" then
@@ -641,13 +645,20 @@ function codeinjections.setformat(s)
else
codeinjections.setxmpfile(xmp_file)
end
- local pdf_version, inject_metadata = spec.pdf_version * 10, spec.inject_metadata
- local majorversion, minorversion = math.div(pdf_version,10), math.mod(pdf_version,10)
+ if not level then
+ level = 3 -- good compromise, default anyway
+ end
+ local pdf_version = spec.pdf_version * 10
+ local inject_metadata = spec.inject_metadata
+ local majorversion = math.div(pdf_version,10)
+ local minorversion = math.mod(pdf_version,10)
local objectcompression = spec.object_compression and pdf_version >= 15
local compresslevel = level or tex.pdfcompresslevel -- keep default
local objectcompresslevel = (objectcompression and (level or tex.pdfobjcompresslevel)) or 0
- tex.pdfcompresslevel, tex.pdfobjcompresslevel = compresslevel, objectcompresslevel
- tex.pdfmajorversion, tex.pdfminorversion = majorversion, minorversion
+ texset("global","pdfcompresslevel",compresslevel)
+ texset("global","pdfobjcompresslevel",objectcompresslevel)
+ texset("global","pdfmajorversion",majorversion)
+ texset("global","pdfminorversion",minorversion)
if objectcompression then
report_backend("forcing pdf version %s.%s, compression level %s, object compression level %s",
majorversion,minorversion,compresslevel,objectcompresslevel)
@@ -704,6 +715,11 @@ function codeinjections.setformat(s)
else
report_backend("error, format '%s' is not supported",format)
end
+ elseif level then
+ texset("global","pdfcompresslevel",level)
+ texset("global","pdfobjcompresslevel",level)
+ else
+ -- we ignore this as we hook it in \everysetupbackend
end
end
diff --git a/tex/context/base/lpdf-nod.lua b/tex/context/base/lpdf-nod.lua
index fe0c975f7..0ce589c32 100644
--- a/tex/context/base/lpdf-nod.lua
+++ b/tex/context/base/lpdf-nod.lua
@@ -59,7 +59,7 @@ end
function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty)
local t = copy_node(pdfsetmatrix)
- t.data = format("%s %s %s %s",rs or 0,sx or 0,sy or 0,rx or 0) -- todo: tx ty
+ t.data = format("%s %s %s %s",rx or 0,sx or 0,sy or 0,ry or 0) -- todo: tx ty
return t
end
@@ -69,21 +69,68 @@ 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
- if h and h ~= 0 then t.height = h end
- if d and d ~= 0 then t.depth = d end
- if n then t.objnum = n end
- if data and data ~= "" then t.data = data end
+ if w and w ~= 0 then
+ t.width = w
+ end
+ if h and h ~= 0 then
+ t.height = h
+ end
+ if d and d ~= 0 then
+ t.depth = d
+ end
+ if n then
+ t.objnum = n
+ end
+ if data and data ~= "" then
+ t.data = data
+ end
return t
end
+-- (!) The next code in pdfdest.w is wrong:
+--
+-- case pdf_dest_xyz:
+-- if (matrixused()) {
+-- set_rect_dimens(pdf, p, parent_box, cur, alt_rule, pdf_dest_margin) ;
+-- } else {
+-- pdf_ann_left(p) = pos.h ;
+-- pdf_ann_top (p) = pos.v ;
+-- }
+-- break ;
+--
+-- so we need to force a matrix.
+
function nodepool.pdfdestination(w,h,d,name,view,n)
local t = copy_node(pdfdest)
- if w and w ~= 0 then t.width = w end
- if h and h ~= 0 then t.height = h end
- if d and d ~= 0 then t.depth = d end
- if n then t.objnum = n end
+ local hasdimensions = false
+ if w and w ~= 0 then
+ t.width = w
+ hasdimensions = true
+ end
+ if h and h ~= 0 then
+ t.height = h
+ hasdimensions = true
+ end
+ if d and d ~= 0 then
+ t.depth = d
+ hasdimensions = true
+ end
+ if n then
+ t.objnum = n
+ end
+ view = views[view] or view or 1 -- fit is default
t.dest_id = name
- t.dest_type = views[view] or view or 1 -- fit is default
- return t
+ t.dest_type = view
+ if hasdimensions and view == 0 then -- xyz
+ -- see (!) s -> m -> t -> r
+ local s = copy_node(pdfsave)
+ local m = copy_node(pdfsetmatrix)
+ local r = copy_node(pdfrestore)
+ m.data = format("1 0 0 1")
+ s.next = m m.next = t t.next = r
+ m.prev = s t.prev = m r.prev = t
+ return s -- a list
+ else
+ return t
+ end
end
diff --git a/tex/context/base/lpdf-ren.lua b/tex/context/base/lpdf-ren.lua
index e0c4b1973..6af65f9de 100644
--- a/tex/context/base/lpdf-ren.lua
+++ b/tex/context/base/lpdf-ren.lua
@@ -9,7 +9,8 @@ if not modules then modules = { } end modules ['lpdf-ren'] = {
-- rendering
local tostring, tonumber, next = tostring, tonumber, next
-local format = string.format
+local format, rep = string.format, string.rep
+local concat = table.concat
local settings_to_array = utilities.parsers.settings_to_array
local backends, lpdf, nodes, node = backends, lpdf, nodes, node
@@ -60,51 +61,12 @@ local lpdf_usage = pdfdictionary { Print = pdfdictionary { PrintState = pdf_off
-- 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, { }
+local alphabetic = { }
local specifications = { }
local initialized = { }
@@ -149,6 +111,7 @@ local function useviewerlayer(name) -- move up so that we can use it as local
cache[#cache+1] = { dn, dd }
pdfld[tag] = dr
textlayers[#textlayers+1] = nr
+ alphabetic[tag] = nr
if specification.visible == v_start then
videlayers[#videlayers+1] = nr
else
@@ -185,11 +148,16 @@ local function flushtextlayers()
pdfflushobject(ci[1],ci[2])
end
if textlayers and #textlayers > 0 then -- we can group them if needed, like: layout
+ local sortedlayers = { }
+ for k, v in table.sortedhash(alphabetic) do
+ sortedlayers[#sortedlayers+1] = v -- maybe do a proper numeric sort as well
+ end
local d = pdfdictionary {
OCGs = textlayers,
D = pdfdictionary {
Name = "Document",
- Order = (viewerlayers.hasorder and textlayers) or nil,
+ -- Order = (viewerlayers.hasorder and textlayers) or nil,
+ Order = (viewerlayers.hasorder and sortedlayers) or nil,
ON = videlayers,
OFF = hidelayers,
BaseState = pdf_on,
@@ -230,6 +198,74 @@ function executers.hidelayer (arguments) return setlayer(pdf_off, arguments)
function executers.videlayer (arguments) return setlayer(pdf_on, arguments) end
function executers.togglelayer(arguments) return setlayer(pdf_toggle,arguments) end
+-- injection
+
+function codeinjections.startlayer(name) -- used in mp
+ if not name then
+ name = "unknown"
+ end
+ useviewerlayer(name)
+ return format("/OC /%s BDC",name)
+end
+
+function codeinjections.stoplayer(name) -- used in mp
+ return "EMC"
+end
+
+local cache = { }
+
+function nodeinjections.startlayer(name)
+ local c = cache[name]
+ if not c then
+ 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
+
+-- experimental stacker code (slow, can be optimized): !!!! TEST CODE !!!!
+
+local values = viewerlayers.values
+local startlayer = codeinjections.startlayer
+local stoplayer = codeinjections.stoplayer
+
+function nodeinjections.startstackedlayer(s,t,first,last)
+ local r = { }
+ for i=first,last do
+ r[#r+1] = startlayer(values[t[i]])
+ end
+ r = concat(r," ")
+ return pdfliteral(r)
+end
+
+function nodeinjections.stopstackedlayer(s,t,first,last)
+ local r = { }
+ for i=last,first,-1 do
+ r[#r+1] = stoplayer()
+ end
+ r = concat(r," ")
+ return pdfliteral(r)
+end
+
+function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2)
+ local r = { }
+ for i=last1,first1,-1 do
+ r[#r+1] = stoplayer()
+ end
+ for i=first2,last2 do
+ r[#r+1] = startlayer(values[t2[i]])
+ end
+ r = concat(r," ")
+ return pdfliteral(r)
+end
+
-- transitions
local pagetransitions = {
diff --git a/tex/context/base/lpdf-u3d.lua b/tex/context/base/lpdf-u3d.lua
index ac6038997..f5f66a487 100644
--- a/tex/context/base/lpdf-u3d.lua
+++ b/tex/context/base/lpdf-u3d.lua
@@ -370,7 +370,7 @@ local function insert3d(spec) -- width, height, factor, display, controls, label
subtype = "PRC"
elseif find(subdata,"^U3D") then
subtype = "U3D"
- elseif file.extname(foundname) == "prc" then
+ elseif file.suffix(foundname) == "prc" then
subtype = "PRC"
end
diff --git a/tex/context/base/luat-bwc.lua b/tex/context/base/luat-bwc.lua
index f893c7c5b..993de7bf3 100644
--- a/tex/context/base/luat-bwc.lua
+++ b/tex/context/base/luat-bwc.lua
@@ -27,6 +27,6 @@ if not tex.wd then
__newindex = function(t,k,v) local bk = box[k] if bk then bk.depth = v end end,
} )
---~ tex.wd, tex.ht, tex.dp = wd, ht, dp
+ -- tex.wd, tex.ht, tex.dp = wd, ht, dp
end
diff --git a/tex/context/base/luat-cbk.lua b/tex/context/base/luat-cbk.lua
index 6622c64cd..c4f0aba02 100644
--- a/tex/context/base/luat-cbk.lua
+++ b/tex/context/base/luat-cbk.lua
@@ -34,10 +34,13 @@ functions.</p>
local trace_callbacks = false trackers.register("system.callbacks", function(v) trace_callbacks = v end)
local trace_calls = false -- only used when analyzing performance and initializations
-local register_callback, find_callback, list_callbacks = callback.register, callback.find, callback.list
+local register_callback = callback.register
+local find_callback = callback.find
+local list_callbacks = callback.list
+
local frozen, stack, list = { }, { }, callbacks.list
-if not callbacks.list then -- otherwise counters get reset
+if not list then -- otherwise counters get reset
list = utilities.storage.allocate(list_callbacks())
@@ -113,15 +116,6 @@ function callbacks.report()
end
end
-function callbacks.table()
- local NC, NR, verbatim = context.NC, context.NR, context.type
- context.starttabulate { "|l|l|p|" }
- for name, _ in sortedhash(list) do
- NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR()
- end
- context.stoptabulate()
-end
-
function callbacks.freeze(name,freeze)
freeze = type(freeze) == "string" and freeze
if find(name,"%*") then
@@ -311,3 +305,16 @@ function garbagecollector.check(size,criterium)
end
end
end
+
+-- this will move
+
+commands = commands or { }
+
+function commands.showcallbacks()
+ local NC, NR, verbatim = context.NC, context.NR, context.type
+ context.starttabulate { "|l|l|p|" }
+ for name, _ in sortedhash(list) do
+ NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR()
+ end
+ context.stoptabulate()
+end
diff --git a/tex/context/base/luat-cnf.lua b/tex/context/base/luat-cnf.lua
index 609dc412b..07a5d51f2 100644
--- a/tex/context/base/luat-cnf.lua
+++ b/tex/context/base/luat-cnf.lua
@@ -123,19 +123,20 @@ function texconfig.init()
local function init(start)
local b = lua.bytecode
local i = start
+ local t = os.clock()
while b[i] do
b[i]() ;
b[i] = nil ;
i = i + 1
-- collectgarbage('step')
end
- return i - start
+ return i - start, os.clock() - t
end
-- the stored tables and modules
- storage.noftables = init(0)
- storage.nofmodules = init(%s)
+ storage.noftables , storage.toftables = init(0)
+ storage.nofmodules, storage.tofmodules = init(%s)
end
diff --git a/tex/context/base/luat-cod.lua b/tex/context/base/luat-cod.lua
index b022f31c3..87b2c0059 100644
--- a/tex/context/base/luat-cod.lua
+++ b/tex/context/base/luat-cod.lua
@@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['luat-cod'] = {
license = "see context related readme files"
}
+local type, loadfile = type, loadfile
local match, gsub, find, format = string.match, string.gsub, string.find, string.format
local texconfig, lua = texconfig, lua
@@ -19,11 +20,13 @@ texconfig.max_in_open = 127
-- registering bytecode chunks
-lua.bytecode = lua.bytecode or { } -- built in anyway
-lua.bytedata = lua.bytedata or { }
-lua.bytedone = lua.bytedone or { }
+local bytecode = lua.bytecode or { }
+local bytedata = lua.bytedata or { }
+local bytedone = lua.bytedone or { }
-local bytecode, bytedata, bytedone = lua.bytecode, lua.bytedata, lua.bytedone
+lua.bytecode = bytecode -- built in anyway
+lua.bytedata = bytedata
+lua.bytedone = bytedone
lua.firstbytecode = 501
lua.lastbytecode = lua.lastbytecode or (lua.firstbytecode - 1) -- as we load ourselves again ... maybe return earlier
@@ -32,18 +35,19 @@ function lua.registeredcodes()
return lua.lastbytecode - lua.firstbytecode + 1
end
+-- no file.* functions yet
+
function lua.registercode(filename,version)
local barename = gsub(filename,"%.[%a%d]+$","")
if barename == filename then filename = filename .. ".lua" end
local basename = match(barename,"^.+[/\\](.-)$") or barename
- if not bytedone[barename] then
+ if not bytedone[basename] then
local code = environment.luafilechunk(filename)
if code then
- assert(code)()
- bytedone[barename] = true
+ bytedone[basename] = true
if environment.initex then
local n = lua.lastbytecode + 1
- bytedata[n] = { barename, version }
+ bytedata[n] = { barename, version or "0.000" }
bytecode[n] = code
lua.lastbytecode = n
end
@@ -54,10 +58,11 @@ end
local finalizers = { }
function lua.registerfinalizer(f,comment)
+ comment = comment or "unknown"
if type(f) == "function" then
finalizers[#finalizers+1] = { action = f, comment = comment }
else
- print(format("fatal error: invalid finalizer, action: %s",finalizer.comment or "unknown"))
+ texio.write_nl(format("fatal error: invalid finalizer, action: %s",comment))
os.exit()
end
end
@@ -98,12 +103,15 @@ if not environment.luafilechunk then
end
local data = loadfile(filename)
texio.write("<",data and "+ " or "- ",filename,">")
+ if data then
+ data()
+ end
return data
end
end
-if not environment.engineflags then
+if not environment.engineflags then -- raw flags
local engineflags = { }
for i=-10,#arg do
local a = arg[i]
diff --git a/tex/context/base/luat-cod.mkiv b/tex/context/base/luat-cod.mkiv
index 930532df9..034ab0613 100644
--- a/tex/context/base/luat-cod.mkiv
+++ b/tex/context/base/luat-cod.mkiv
@@ -15,12 +15,6 @@
\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}
-
%D We cannot use the following due to the fact that existing usage
%D demanded duplicating hashes.
%D
diff --git a/tex/context/base/luat-env.lua b/tex/context/base/luat-env.lua
index 4f1b661c2..c8a391e76 100644
--- a/tex/context/base/luat-env.lua
+++ b/tex/context/base/luat-env.lua
@@ -20,7 +20,8 @@ local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
local unquoted, quoted = string.unquoted, string.quoted
-local concat = table.concat
+local concat, insert, remove = table.concat, table.insert, table.remove
+local loadedluacode = utilities.lua.loadedluacode
-- precautions
@@ -38,8 +39,28 @@ if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaon
for k=3,#arg do
arg[k-2] = arg[k]
end
- arg[#arg] = nil -- last
- arg[#arg] = nil -- pre-last
+ remove(arg) -- last
+ remove(arg) -- pre-last
+end
+
+-- This is an ugly hack but it permits symlinking a script (say 'context') to 'mtxrun' as in:
+--
+-- ln -s /opt/minimals/tex/texmf-linux-64/bin/mtxrun context
+--
+-- The special mapping hack is needed because 'luatools' boils down to 'mtxrun --script base'
+-- but it's unlikely that there will be more of this
+
+do
+
+ local originalzero = file.basename(arg[0])
+ local specialmapping = { luatools == "base" }
+
+ if originalzero ~= "mtxrun" and originalzero ~= "mtxrun.lua" then
+ arg[0] = specialmapping[originalzero] or originalzero
+ insert(arg,0,"--script")
+ insert(arg,0,"mtxrun")
+ end
+
end
-- environment
@@ -79,6 +100,8 @@ local mt = {
setmetatable(environment,mt)
+-- context specific arguments (in order not to confuse the engine)
+
function environment.initializearguments(arg)
local arguments, files = { }, { }
environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
@@ -87,10 +110,12 @@ function environment.initializearguments(arg)
if index > 0 then
local flag, value = match(argument,"^%-+(.-)=(.-)$")
if flag then
+ flag = gsub(flag,"^c:","")
arguments[flag] = unquoted(value or "")
else
flag = match(argument,"^%-+(.+)")
if flag then
+ flag = gsub(flag,"^c:","")
arguments[flag] = true
else
files[#files+1] = argument
@@ -110,7 +135,7 @@ end
-- tricky: too many hits when we support partials unless we add
-- a registration of arguments so from now on we have 'partial'
-function environment.argument(name,partial)
+function environment.getargument(name,partial)
local arguments, sortedflags = environment.arguments, environment.sortedflags
if arguments[name] then
return arguments[name]
@@ -133,6 +158,8 @@ function environment.argument(name,partial)
return nil
end
+environment.argument = environment.getargument
+
function environment.splitarguments(separator) -- rather special, cut-off before separator
local done, before, after = false, { }, { }
local originalarguments = environment.originalarguments
@@ -234,7 +261,7 @@ function environment.texfile(filename)
return resolvers.findfile(filename,'tex')
end
-function environment.luafile(filename)
+function environment.luafile(filename) -- needs checking
local resolved = resolvers.findfile(filename,'tex') or ""
if resolved ~= "" then
return resolved
@@ -246,13 +273,16 @@ function environment.luafile(filename)
return resolvers.findfile(filename,'luatexlibs') or ""
end
-environment.loadedluacode = loadfile -- can be overloaded
+local function checkstrip(filename)
+ local modu = modules[file.nameonly(filename)]
+ return modu and modu.dataonly
+end
function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format
filename = file.replacesuffix(filename, "lua")
local fullname = environment.luafile(filename)
if fullname and fullname ~= "" then
- local data = environment.loadedluacode(fullname)
+ local data = loadedluacode(fullname,checkstrip,filename)
if trace_locating then
report_lua("loading file %s%s", fullname, not data and " failed" or "")
elseif not silent then
diff --git a/tex/context/base/luat-fmt.lua b/tex/context/base/luat-fmt.lua
index cfb9a0bb7..37b0f5166 100644
--- a/tex/context/base/luat-fmt.lua
+++ b/tex/context/base/luat-fmt.lua
@@ -110,7 +110,6 @@ function environment.make_format(name)
end
function environment.run_format(name,data,more)
- -- hm, rather old code here; we can now use the file.whatever functions
if name and name ~= "" then
local barename = file.removesuffix(name)
local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
diff --git a/tex/context/base/luat-ini.lua b/tex/context/base/luat-ini.lua
index 204cc7bd1..94c878eb1 100644
--- a/tex/context/base/luat-ini.lua
+++ b/tex/context/base/luat-ini.lua
@@ -8,12 +8,11 @@ if not modules then modules = { } end modules ['luat-ini'] = {
-- rather experimental down here ... will change with lua 5.2 --
-local debug = require "debug"
+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 mark = utilities.storage.mark
-
--[[ldx--
<p>We cannot load anything yet. However what we will do us reserve a fewtables.
These can be used for runtime user data or third party modules and will not be
@@ -26,15 +25,6 @@ moduledata = moduledata or { } -- only for development team
documentdata = documentdata or { } -- for users (e.g. raw data)
parametersets = parametersets or { } -- experimental for team
-document = document or { } -- only for context itself
-
---[[ldx--
-<p>These can be used/set by the caller program; <t>mtx-context.lua</t> does it.</p>
---ldx]]--
-
-document.arguments = mark(document.arguments or { })
-document.files = mark(document.files or { })
-
--[[ldx--
<p>Please create a namespace within these tables before using them!</p>
@@ -157,33 +147,3 @@ end
storage.register("lua/numbers", lua.numbers, "lua.numbers")
storage.register("lua/messages", lua.messages, "lua.messages")
-
---~ local arguments, files = document.arguments, document.files -- set later
-
-function document.setargument(key,value)
- document.arguments[key] = value
-end
-
-function document.setdefaultargument(key,default)
- local v = document.arguments[key]
- if v == nil or v == "" then
- document.arguments[key] = default
- end
-end
-
-function document.getargument(key,default)
- local v = document.arguments[key]
- if type(v) == "boolean" then
- v = (v and "yes") or "no"
- document.arguments[key] = v
- end
- context(v or default or "")
-end
-
-function document.setfilename(i,name)
- document.files[tonumber(i)] = name
-end
-
-function document.getfilename(i)
- context(document.files[i] or "")
-end
diff --git a/tex/context/base/luat-ini.mkiv b/tex/context/base/luat-ini.mkiv
index 46b2d1f7f..094c4ee53 100644
--- a/tex/context/base/luat-ini.mkiv
+++ b/tex/context/base/luat-ini.mkiv
@@ -108,16 +108,18 @@
%D Beware: because \type {\expanded} is een convert command, the error
%D message will show \type{<inserted text>} as part of the message.
+\installcorenamespace{luacode}
+
\def\luat_start_named_lua_code#1%
{\begingroup
\obeylualines
\obeyluatokens
- \csname\??lu:c:#1\endcsname}
+ \csname\??luacode#1\endcsname}
\unexpanded\def\definenamedlua[#1]#2[#3]% no optional arg handling here yet
- {\ifcsname\??lu:c:#1\endcsname \else
+ {\ifcsname\??luacode#1\endcsname \else
\scratchcounter\ctxlua{lua.registername("#1","#3")}%
- \normalexpanded{\edef\csname\??lu:c:#1\endcsname##1\csname\e!stop#1\v!code\endcsname}%
+ \normalexpanded{\edef\csname\??luacode#1\endcsname##1\csname\e!stop#1\v!code\endcsname}%
{\endgroup\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}}%
diff --git a/tex/context/base/luat-lib.mkiv b/tex/context/base/luat-lib.mkiv
index 5a53b7ea2..6ca0ac05a 100644
--- a/tex/context/base/luat-lib.mkiv
+++ b/tex/context/base/luat-lib.mkiv
@@ -30,6 +30,10 @@
\registerctxluafile{trac-log}{1.001}
%registerctxluafile{trac-pro}{1.001}
+\registerctxluafile{util-tpl}{1.001} % needs tracker
+
+\registerctxluafile{util-sta}{1.001}
+
\registerctxluafile{data-ini}{1.001}
\registerctxluafile{data-exp}{1.001}
\registerctxluafile{data-env}{1.001}
@@ -65,6 +69,7 @@
\registerctxluafile{luat-exe}{1.001}
\registerctxluafile{luat-iop}{1.001}
\registerctxluafile{luat-bwc}{1.001}
+\registerctxluafile{trac-lmx}{1.001} % might become l-lmx or luat-lmx
\registerctxluafile{luat-mac}{1.001}
\registerctxluafile{lxml-tab}{1.001}
diff --git a/tex/context/base/luat-mac.lua b/tex/context/base/luat-mac.lua
index f8f87a25a..199332bba 100644
--- a/tex/context/base/luat-mac.lua
+++ b/tex/context/base/luat-mac.lua
@@ -20,6 +20,8 @@ local lpegmatch, patterns = lpeg.match, lpeg.patterns
local insert, remove = table.insert, table.remove
local rep, sub = string.rep, string.sub
local setmetatable = setmetatable
+local filesuffix = file.suffix
+local convertlmxstring = lmx.convertstring
local pushtarget, poptarget = logs.pushtarget, logs.poptarget
@@ -199,18 +201,91 @@ function macros.version(data)
return lpegmatch(checker,data)
end
+-- function macros.processmkvi(str,filename)
+-- if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+-- local oldsize = #str
+-- str = lpegmatch(parser,str,1,true) or str
+-- pushtarget("log")
+-- report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str)
+-- poptarget("log")
+-- end
+-- return str
+-- end
+--
+-- utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi")
+
+-- the document variables hack is temporary
+
+local processors = { }
+
+function processors.mkvi(str,filename)
+ local oldsize = #str
+ str = lpegmatch(parser,str,1,true) or str
+ pushtarget("log")
+ report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function processors.mkix(str,filename) -- we could intercept earlier so that caching works better
+ if not document then -- because now we hash the string as well as the
+ document = { }
+ end
+ if not document.variables then
+ document.variables = { }
+ end
+ local oldsize = #str
+ str = convertlmxstring(str,document.variables,false) or str
+ pushtarget("log")
+ report_macros("processed mkix file %q, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function processors.mkxi(str,filename)
+ if not document then
+ document = { }
+ end
+ if not document.variables then
+ document.variables = { }
+ end
+ local oldsize = #str
+ str = convertlmxstring(str,document.variables,false) or str
+ str = lpegmatch(parser,str,1,true) or str
+ pushtarget("log")
+ report_macros("processed mkxi file %q, delta %s",filename,oldsize-#str)
+ poptarget("log")
+ return str
+end
+
+function macros.processmk(str,filename)
+ if filename then
+ local suffix = filesuffix(filename)
+ local processor = processors[suffix] or processors[lpegmatch(checker,str)]
+ if processor then
+ str = processor(str,filename)
+ end
+ end
+ return str
+end
+
+utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmk")
+
function macros.processmkvi(str,filename)
- if (filename and file.suffix(filename) == "mkvi") or lpegmatch(checker,str) == "mkvi" then
- local result = lpegmatch(parser,str,1,true) or str
+ if filename and filesuffix(filename) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+ local oldsize = #str
+ str = lpegmatch(parser,str,1,true) or str
pushtarget("log")
- report_macros("processed file '%s', delta %s",filename,#str-#result)
+ report_macros("processed mkvi file %q, delta %s",filename,oldsize-#str)
poptarget("log")
- return result
- else
- return str
end
+ return str
end
+utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi")
+
+-- bonus
+
if resolvers.schemes then
local function handler(protocol,name,cachename)
@@ -218,7 +293,7 @@ if resolvers.schemes then
local path = hashed.path
if path and path ~= "" then
local str = resolvers.loadtexfile(path)
- if file.suffix(path) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
+ if filesuffix(path) == "mkvi" or lpegmatch(checker,str) == "mkvi" then
-- already done automatically
io.savedata(cachename,str)
else
@@ -234,9 +309,6 @@ if resolvers.schemes then
resolvers.schemes.install('mkvi',handler,1) -- this will cache !
- utilities.sequencers.appendaction(resolvers.openers.helpers.textfileactions,"system","resolvers.macros.processmkvi")
- -- utilities.sequencers.disableaction(resolvers.openers.helpers.textfileactions,"resolvers.macros.processmkvi")
-
end
-- print(macros.preprocessed(
diff --git a/tex/context/base/luat-run.lua b/tex/context/base/luat-run.lua
index ce25d1f55..bcd9e2bdc 100644
--- a/tex/context/base/luat-run.lua
+++ b/tex/context/base/luat-run.lua
@@ -67,11 +67,11 @@ end
local function report_output_log()
end
---~ local function show_open()
---~ end
+-- local function show_open()
+-- end
---~ local function show_close()
---~ end
+-- local function show_close()
+-- end
local function pre_dump_actions()
lua.finalize(trace_lua_dump and report_lua or nil)
@@ -84,8 +84,8 @@ end
callbacks.register('start_run', start_run, "actions performed at the beginning of a run")
callbacks.register('stop_run', stop_run, "actions performed at the end of a run")
---~ callbacks.register('show_open', show_open, "actions performed when opening a file")
---~ callbacks.register('show_close', show_close, "actions performed when closing a file")
+---------.register('show_open', show_open, "actions performed when opening a file")
+---------.register('show_close', show_close, "actions performed when closing a file")
callbacks.register('report_output_pages', report_output_pages, "actions performed when reporting pages")
callbacks.register('report_output_log', report_output_log, "actions performed when reporting log file")
diff --git a/tex/context/base/luat-soc.lua b/tex/context/base/luat-soc.lua
index 1095ed087..9342a4b33 100644
--- a/tex/context/base/luat-soc.lua
+++ b/tex/context/base/luat-soc.lua
@@ -1,11 +1,11 @@
-- This is just a loader. The package handler knows about the TEX tree.
---~ require "luatex/lua/socket.lua"
---~ require "luatex/lua/ltn12.lua"
---~ require "luatex/lua/mime.lua"
---~ require "luatex/lua/socket/http.lua"
---~ require "luatex/lua/socket/url.lua"
---~ require "luatex/lua/socket/tp.lua"
---~ require "luatex/lua/socket/ftp.lua"
+-- require "luatex/lua/socket.lua"
+-- require "luatex/lua/ltn12.lua"
+-- require "luatex/lua/mime.lua"
+-- require "luatex/lua/socket/http.lua"
+-- require "luatex/lua/socket/url.lua"
+-- require "luatex/lua/socket/tp.lua"
+-- require "luatex/lua/socket/ftp.lua"
--- "luatex/lua/socket/smtp.lua"
+-- "luatex/lua/socket/smtp.lua"
diff --git a/tex/context/base/luat-sto.lua b/tex/context/base/luat-sto.lua
index 30bb7d5bb..fddf262c2 100644
--- a/tex/context/base/luat-sto.lua
+++ b/tex/context/base/luat-sto.lua
@@ -12,7 +12,9 @@ local type, next, setmetatable, getmetatable, collectgarbage = type, next, setme
local gmatch, format, write_nl = string.gmatch, string.format, texio.write_nl
local serialize, concat, sortedhash = table.serialize, table.concat, table.sortedhash
local bytecode = lua.bytecode
+local strippedloadstring = utilities.lua.strippedloadstring
+local trace_storage = false
local report_storage = logs.reporter("system","storage")
storage = storage or { }
@@ -62,11 +64,14 @@ local function dump()
end
max = max + 1
if trace_storage then
- report_storage('saving %s in slot %s',message,max)
- c = c + 1 ; code[c] = format("report_storage('restoring %s from slot %s')",message,max)
+ c = c + 1 ; code[c] = format("print('restoring %s from slot %s')",message,max)
end
c = c + 1 ; code[c] = serialize(original,name)
- bytecode[max] = loadstring(concat(code,"\n"))
+ if trace_storage then
+ report_storage('saving %s in slot %s (%s bytes)',message,max,#code[c])
+ end
+ -- we don't need tracing in such tables
+ bytecode[max] = strippedloadstring(concat(code,"\n"),true,format("slot %s",max))
collectgarbage("step")
end
storage.max = max
@@ -103,9 +108,24 @@ end
--~ end
statistics.register("stored bytecode data", function()
- local modules = (storage.nofmodules > 0 and storage.nofmodules) or (status.luabytecodes - lua.firstbytecode - 1)
- local dumps = (storage.noftables > 0 and storage.noftables) or storage.max-storage.min + 1
- return format("%s modules, %s tables, %s chunks",modules,dumps,modules+dumps)
+ local nofmodules = (storage.nofmodules > 0 and storage.nofmodules) or (status.luabytecodes - lua.firstbytecode - 1)
+ local nofdumps = (storage.noftables > 0 and storage.noftables ) or storage.max-storage.min + 1
+ local tofmodules = storage.tofmodules or 0
+ local tofdumps = storage.toftables or 0
+ if environment.initex then
+ return format("%s modules, %s tables, %s chunks, %s bytes stripped (%s chunks)",
+ nofmodules,
+ nofdumps,
+ nofmodules + nofdumps,
+ utilities.lua.nofstrippedbytes, utilities.lua.nofstrippedchunks
+ )
+ else
+ return format("%s modules (%0.3f sec), %s tables (%0.3f sec), %s chunks (%0.3f sec)",
+ nofmodules, tofmodules,
+ nofdumps, tofdumps,
+ nofmodules + nofdumps, tofmodules + tofdumps
+ )
+ end
end)
if lua.bytedata then
diff --git a/tex/context/base/lxml-css.lua b/tex/context/base/lxml-css.lua
index 112a5e75d..c5a85c2bd 100644
--- a/tex/context/base/lxml-css.lua
+++ b/tex/context/base/lxml-css.lua
@@ -24,22 +24,49 @@ local cmf = 1/dimenfactors.cm
local mmf = 1/dimenfactors.mm
local inf = 1/dimenfactors["in"]
+local percentage, exheight, emwidth, pixels
+
+if tex then
+
+ local exheights = fonts.hashes.exheights
+ local emwidths = fonts.hashes.emwidths
+
+ percentage = function(s,pcf) return tonumber(s) * (pcf or tex.hsize) end
+ exheight = function(s,exf) return tonumber(s) * (exf or exheights[true]) end
+ emwidth = function(s,emf) return tonumber(s) * (emf or emwidths[true]) end
+ pixels = function(s,pxf) return tonumber(s) * (pxf or emwidths[true]/300) end
+
+else
+
+ local function generic(s,unit) return tonumber(s) * unit end
+
+ percentage = generic
+ exheight = generic
+ emwidth = generic
+ pixels = generic
+
+end
+
local validdimen = Cg(lpegpatterns.number,'a') * (
- Cb('a') * P("pt") / function(s) return tonumber(s) * bpf end
- + Cb('a') * P("cm") / function(s) return tonumber(s) * cmf end
- + Cb('a') * P("mm") / function(s) return tonumber(s) * mmf end
- + Cb('a') * P("in") / function(s) return tonumber(s) * inf end
- + Cb('a') * P("px") * Carg(1) / function(s,pxf) return tonumber(s) * pxf end
- + Cb('a') * P("%") * Carg(2) / function(s,pcf) return tonumber(s) * pcf end
- + Cb('a') * P("ex") * Carg(3) / function(s,exf) return tonumber(s) * exf end
- + Cb('a') * P("em") * Carg(4) / function(s,emf) return tonumber(s) * emf end
- + Cb('a') * Carg(1) / function(s,pxf) return tonumber(s) * pxf end
+ Cb('a') * P("pt") / function(s) return tonumber(s) * bpf end
+ + Cb('a') * P("cm") / function(s) return tonumber(s) * cmf end
+ + Cb('a') * P("mm") / function(s) return tonumber(s) * mmf end
+ + Cb('a') * P("in") / function(s) return tonumber(s) * inf end
+ + Cb('a') * P("px") * Carg(1) / pixels
+ + Cb('a') * P("%") * Carg(2) / percentage
+ + Cb('a') * P("ex") * Carg(3) / exheight
+ + Cb('a') * P("em") * Carg(4) / emwidth
+ + Cb('a') * Carg(1) / pixels
)
local pattern = (validdimen * lpegpatterns.whitespace^0)^1
-- todo: default if ""
+local function dimension(str,pixel,percent,exheight,emwidth)
+ return (lpegmatch(pattern,str,1,pixel,percent,exheight,emwidth))
+end
+
local function padding(str,pixel,percent,exheight,emwidth)
local top, bottom, left, right = lpegmatch(pattern,str,1,pixel,percent,exheight,emwidth)
if not bottom then
@@ -52,7 +79,8 @@ local function padding(str,pixel,percent,exheight,emwidth)
return top, bottom, left, right
end
-css.padding = padding
+css.dimension = dimension
+css.padding = padding
-- local hsize = 655360*100
-- local exheight = 65536*4
diff --git a/tex/context/base/lxml-ctx.mkiv b/tex/context/base/lxml-ctx.mkiv
index 530c29aa7..58807339d 100644
--- a/tex/context/base/lxml-ctx.mkiv
+++ b/tex/context/base/lxml-ctx.mkiv
@@ -20,9 +20,6 @@
\unprotect
-% The \let|=letterbar is a messy hack and is needed for the tabulate. We now use
-% \detokenize.
-
\settrue \xmllshowbuffer
\setfalse\xmllshowtitle
\settrue \xmllshowwarning
diff --git a/tex/context/base/lxml-ini.mkiv b/tex/context/base/lxml-ini.mkiv
index 84ebc5823..73cd4be7e 100644
--- a/tex/context/base/lxml-ini.mkiv
+++ b/tex/context/base/lxml-ini.mkiv
@@ -186,7 +186,7 @@
\unexpanded\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata}
\unexpanded\def\xmlprocessbuffer {\lxml_process\zerocount\xmlloadbuffer}
\unexpanded\def\xmlprocessregistered{\lxml_process\zerocount\xmlloadregistered}
-\let\xmlprocess \xmlprocessfile
+ \let\xmlprocess \xmlprocessfile
\startxmlsetups xml:flush
\xmlflush{#1}
@@ -313,7 +313,7 @@
\xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone
\to \everysetupxml
-\unexpanded\def\xmlinitialize
+\unexpanded\def\initializexmlprocessing % is this still needed?
{\the\everysetupxml}
\let\p_lxml_entities\empty
diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua
index 44dd97155..0c10998a0 100644
--- a/tex/context/base/lxml-lpt.lua
+++ b/tex/context/base/lxml-lpt.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['lxml-pth'] = {
+if not modules then modules = { } end modules ['lxml-lpt'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -539,14 +539,23 @@ local lp_builtin = P (
-- for the moment we keep namespaces with attributes
local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])")
-local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end)
-local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end)
+
+-- lp_fastpos_p = (P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end
+-- lp_fastpos_n = (P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end
+
+lp_fastpos_p = P("+")^0 * R("09")^1 * P(-1) / "l==%0"
+lp_fastpos_n = P("-") * R("09")^1 * P(-1) / "(%0<0 and (#list+%0==l))"
+
local lp_fastpos = lp_fastpos_n + lp_fastpos_p
+
local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
-local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
- return t .. "("
-end
+-- local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
+-- return t .. "("
+-- end
+
+-- local lp_lua_function = (R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / "%0("
+local lp_lua_function = Cs((R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(")) / "%0"
local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
if expressions[t] then
@@ -1197,12 +1206,12 @@ xml.selection = selection -- new method, simple handle
-- generic function finalizer (independant namespace)
-local function dofunction(collected,fnc)
+local function dofunction(collected,fnc,...)
if collected then
local f = functions[fnc]
if f then
for c=1,#collected do
- f(collected[c])
+ f(collected[c],...)
end
else
report_lpath("unknown function '%s'",fnc)
@@ -1357,3 +1366,29 @@ function xml.inspect(collection,pattern)
report_lpath("pattern %q\n\n%s\n",pattern,xml.tostring(e))
end
end
+
+-- texy (see xfdf):
+
+local function split(e)
+ local dt = e.dt
+ if dt then
+ for i=1,#dt do
+ local dti = dt[i]
+ if type(dti) == "string" then
+ dti = gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1")
+ dti = gsub(dti,"[\n\r]+","\n\n")
+ dt[i] = dti
+ else
+ split(dti)
+ end
+ end
+ end
+ return e
+end
+
+function xml.finalizers.paragraphs(c)
+ for i=1,#c do
+ split(c[i])
+ end
+ return c
+end
diff --git a/tex/context/base/lxml-tab.lua b/tex/context/base/lxml-tab.lua
index b5c860787..6b23953cc 100644
--- a/tex/context/base/lxml-tab.lua
+++ b/tex/context/base/lxml-tab.lua
@@ -43,7 +43,7 @@ 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, utffind, utfgsub = utf.char, utf.find, utf.gsub
+local utfchar = utf.char
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
@@ -365,15 +365,7 @@ 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 escaped = utf.remapper(privates_u)
local function unescaped(s)
local p = privates_n[s]
@@ -388,13 +380,7 @@ local function unescaped(s)
return p
end
-local function unprivatized(s,resolve)
- if s == "" then
- return ""
- else
- return (utfgsub(s,".",privates_p))
- end
-end
+local unprivatized = utf.remapper(privates_p)
xml.privatetoken = unescaped
xml.unprivatized = unprivatized
@@ -735,7 +721,12 @@ local function _xmlconvert_(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler(format("load error: %s",errorstr))
+ local currentresource = settings.currentresource
+ if currentresource and currentresource ~= "" then
+ xml.errorhandler(format("load error in [%s]: %s",currentresource,errorstr))
+ else
+ xml.errorhandler(format("load error: %s",errorstr))
+ end
end
end
else
@@ -780,7 +771,7 @@ function xmlconvert(data,settings)
if ok then
return result
else
- return _xmlconvert_("")
+ return _xmlconvert_("",settings)
end
end
@@ -841,7 +832,14 @@ function xml.load(filename,settings)
elseif filename then -- filehandle
data = filename:read("*all")
end
- return xmlconvert(data,settings)
+ if settings then
+ settings.currentresource = filename
+ local result = xmlconvert(data,settings)
+ settings.currentresource = nil
+ return result
+ else
+ return xmlconvert(data,{ currentresource = filename })
+ end
end
--[[ldx--
@@ -907,7 +905,7 @@ function xml.checkbom(root) -- can be made faster
return
end
end
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 1, { special = true, ns = "", tg = "@pi@", dt = { "xml version='1.0' standalone='yes'" } } )
insert(dt, 2, "\n" )
end
end
@@ -1317,7 +1315,7 @@ function xml.tocdata(e,wrapper) -- a few more in the aux module
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
- local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e }
+ local t = { special = true, ns = "", tg = "@cd@", at = { }, rn = "", dt = { whatever }, __p__ = e }
setmetatable(t,getmetatable(e))
e.dt = { t }
end
diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua
index 0b21e0a9c..3f1ec8254 100644
--- a/tex/context/base/lxml-tex.lua
+++ b/tex/context/base/lxml-tex.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['lxml-tst'] = {
+if not modules then modules = { } end modules ['lxml-tex'] = {
version = 1.001,
comment = "companion to lxml-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -25,9 +25,10 @@ local lowerchars, upperchars, lettered = characters.lower, characters.upper, cha
lxml = lxml or { }
local lxml = lxml
-local ctxcatcodes, notcatcodes = tex.ctxcatcodes, tex.notcatcodes
-
-local contextsprint = context.sprint -- with catcodes (here we use fast variants, but with option for tracing)
+local catcodenumbers = catcodes.numbers
+local ctxcatcodes = catcodenumbers.ctxcatcodes -- todo: use different method
+local notcatcodes = catcodenumbers.notcatcodes -- todo: use different method
+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
@@ -381,7 +382,10 @@ function xml.load(filename,settings)
noffiles, nofconverted = noffiles + 1, nofconverted + 1
starttiming(xml)
local ok, data = resolvers.loadbinfile(filename)
+ settings = settings or { }
+ settings.currentresource = filename
local xmltable = xml.convert((ok and data) or "",settings)
+ settings.currentresource = nil
stoptiming(xml)
return xmltable
end
@@ -390,12 +394,13 @@ local function entityconverter(id,str)
return xmlentities[str] or xmlprivatetoken(str) or "" -- roundtrip handler
end
-function lxml.convert(id,data,entities,compress)
+function lxml.convert(id,data,entities,compress,currentresource)
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
+ currentresource = tostring(currentresource or id),
}
if compress and compress == variables.yes then
settings.strip_cm_and_dt = true
@@ -410,13 +415,13 @@ end
function lxml.load(id,filename,compress,entities)
filename = commands.preparedfile(filename) -- not commands!
if trace_loading then
- report_lxml("loading file '%s' as '%s'",filename,id)
+ report_lxml("loading file %q as %q",filename,id)
end
noffiles, nofconverted = noffiles + 1, nofconverted + 1
-- local xmltable = xml.load(filename)
starttiming(xml)
local ok, data = resolvers.loadbinfile(filename)
- local xmltable = lxml.convert(id,(ok and data) or "",compress,entities)
+ local xmltable = lxml.convert(id,(ok and data) or "",compress,entities,format("id: %s, file: %s",id,filename))
stoptiming(xml)
lxml.store(id,xmltable,filename)
return xmltable, filename
@@ -457,14 +462,14 @@ function xml.getbuffer(name,compress,entities) -- we need to make sure that comm
end
nofconverted = nofconverted + 1
local data = buffers.getcontent(name)
- xmltostring(lxml.convert(name,data,compress,entities)) -- one buffer
+ xmltostring(lxml.convert(name,data,compress,entities,format("buffer: %s",tostring(name or "?")))) -- one buffer
end
function lxml.loadbuffer(id,name,compress,entities)
starttiming(xml)
nofconverted = nofconverted + 1
local data = buffers.collectcontent(name or id) -- name can be list
- local xmltable = lxml.convert(id,data,compress,entities)
+ local xmltable = lxml.convert(id,data,compress,entities,format("buffer: %s",tostring(name or id or "?")))
lxml.store(id,xmltable)
stoptiming(xml)
return xmltable, name or id
@@ -473,7 +478,7 @@ end
function lxml.loaddata(id,str,compress,entities)
starttiming(xml)
nofconverted = nofconverted + 1
- local xmltable = lxml.convert(id,str or "",compress,entities)
+ local xmltable = lxml.convert(id,str or "",compress,entities,format("id: %s",id))
lxml.store(id,xmltable)
stoptiming(xml)
return xmltable, id
diff --git a/tex/context/base/m-barcodes.mkiv b/tex/context/base/m-barcodes.mkiv
index 0282f706d..e4c43b376 100644
--- a/tex/context/base/m-barcodes.mkiv
+++ b/tex/context/base/m-barcodes.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D You can best use m-zint instead of this one.
+\writestatus{barcodes}{the 'zint' module is a better choice}
% \startTEXpage
% \startPSTRICKS
@@ -106,15 +106,13 @@ end
}
\stopsetups
-\def\barcode[#1]%
+\unexpanded\def\barcode[#1]%
{\bgroup
\setvariables[barcode][type=isbn,#1]%
\directsetup{barcode:\getvariable{barcode}{type}}%
\egroup}
-% \usemodule[barcodes]
-
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{m-barcodes.mkiv}
\starttext
\startTEXpage
diff --git a/tex/context/base/m-chart.lua b/tex/context/base/m-chart.lua
index 32de8a5ba..a00f246a9 100644
--- a/tex/context/base/m-chart.lua
+++ b/tex/context/base/m-chart.lua
@@ -15,11 +15,11 @@ 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, lpegmatch = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.match
-local P, S, C, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc
-local lpegmatch = lpeg.match
+local report_chart = logs.reporter("chart")
-local points = number.points
+local points = number.points
local variables = interfaces.variables
@@ -27,7 +27,6 @@ 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
@@ -672,7 +671,7 @@ local function process_texts(chart,xoffset,yoffset)
end
end
-local function getchart(settings)
+local function getchart(settings,forced_x,forced_y,forced_nx,forced_ny)
if not settings then
print("no settings given")
return
@@ -688,7 +687,7 @@ local function getchart(settings)
return
end
chart = expanded(chart,settings)
- local cc_settings = chart.settings.chart
+ local chartsettings = chart.settings.chart
local autofocus = chart.settings.chart.autofocus
if autofocus then
autofocus = utilities.parsers.settings_to_hash(autofocus)
@@ -697,10 +696,10 @@ local function getchart(settings)
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 x = forced_x or tonumber(chartsettings.x)
+ local y = forced_y or tonumber(chartsettings.y)
+ local nx = forced_nx or tonumber(chartsettings.nx)
+ local ny = forced_ny or tonumber(chartsettings.ny)
--
local minx, miny, maxx, maxy = 0, 0, 0, 0
local data = chart.data
@@ -715,8 +714,8 @@ local function getchart(settings)
if miny == 0 or y > maxy then maxy = y end
end
end
--- print("1>",x,y,nx,ny)
--- print("2>",minx, miny, maxx, maxy)
+ -- 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
@@ -762,7 +761,9 @@ local function getchart(settings)
end
local function makechart(chart)
- local settings = chart.settings
+ local settings = chart.settings
+ local chartsettings = settings.chart
+ --
context.begingroup()
context.forgetall()
--
@@ -770,27 +771,27 @@ local function makechart(chart)
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
+ if chartsettings.option == v_test or chartsettings.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)
+ elseif chartsettings.dot ~= "" then -- no checking done, private option
+ context("flow_show_%s_points := true ;",chartsettings.dot)
end
--
- local backgroundcolor = settings.chart.backgroundcolor
+ local backgroundcolor = chartsettings.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
+ local shapewidth = chartsettings.width
+ local gridwidth = shapewidth + 2*chartsettings.dx
+ local shapeheight = chartsettings.height
+ local gridheight = shapeheight + 2*chartsettings.dy
+ local chartoffset = chartsettings.offset
+ local labeloffset = chartsettings.labeloffset
+ local exitoffset = chartsettings.exitoffset
+ local commentoffset = chartsettings.commentoffset
context("flow_grid_width := %s ;", points(gridwidth))
context("flow_grid_height := %s ;", points(gridheight))
context("flow_shape_width := %s ;", points(shapewidth))
@@ -802,8 +803,8 @@ local function makechart(chart)
--
local radius = settings.line.radius
local rulethickness = settings.line.rulethickness
- local dx = settings.chart.dx
- local dy = settings.chart.dy
+ local dx = chartsettings.dx
+ local dy = chartsettings.dy
if radius < rulethickness then
radius = 2.5*rulethickness
if radius > dx then
@@ -818,7 +819,7 @@ local function makechart(chart)
context("flow_connection_arrow_size := %s ;", points(radius))
context("flow_connection_dash_size := %s ;", points(radius))
--
- local offset = settings.chart.offset -- todo: pass string
+ local offset = chartsettings.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
@@ -836,42 +837,80 @@ local function makechart(chart)
context.endgroup()
end
+local function splitchart(chart)
+ local settings = chart.settings
+ local splitsettings = settings.split
+ local chartsettings = settings.chart
+ --
+ local name = chartsettings.name
+ --
+ local from_x = chart.from_x
+ local from_y = chart.from_y
+ local to_x = chart.to_x
+ local to_y = chart.to_y
+ --
+ local step_x = splitsettings.nx or to_x
+ local step_y = splitsettings.ny or to_y
+ local delta_x = splitsettings.dx or 0
+ local delta_y = splitsettings.dy or 0
+ --
+ report_chart("spliting %q: from (%s,%s) upto (%s,%s) into (%s,%s) with overlap (%s,%s)",
+ name,from_x,from_y,to_x,to_y,step_x,step_y,delta_x,delta_y)
+ --
+ local part_x = 0
+ local first_x = from_x
+ while true do
+ part_x = part_x + 1
+ local last_x = first_x + step_x - 1
+ local done = last_x >= to_x
+ if done then
+ last_x = to_x
+ end
+ local part_y = 0
+ local first_y = from_y
+ while true do
+ part_y = part_y + 1
+ local last_y = first_y + step_y - 1
+ local done = last_y >= to_y
+ if done then
+ last_y = to_y
+ end
+ --
+ report_chart("part (%s,%s) of %q: (%s,%s) -> (%s,%s)",part_x,part_y,name,first_x,first_y,last_x,last_y)
+ local x, y, nx, ny = first_x, first_y, last_x - first_x + 1,last_y - first_y + 1
+ context.beforeFLOWsplit()
+ context.handleFLOWsplit(function()
+ makechart(getchart(settings,x,y,nx,ny)) -- we need to pass frozen settings !
+ end)
+ context.afterFLOWsplit()
+ --
+ if done then
+ break
+ else
+ first_y = last_y + 1 - delta_y
+ end
+ end
+ if done then
+ break
+ else
+ first_x = last_x + 1 - delta_x
+ end
+ end
+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
+ if settings then
+ local chartsettings = settings.chart
+ if chartsettings and chartsettings.split == v_yes then
+ splitchart(chart)
+ else
+ makechart(chart)
+ end
+ else
makechart(chart)
--- end
+ end
end
end
diff --git a/tex/context/base/m-chart.mkii b/tex/context/base/m-chart.mkii
index 13403966b..8a5f480ee 100644
--- a/tex/context/base/m-chart.mkii
+++ b/tex/context/base/m-chart.mkii
@@ -1094,7 +1094,7 @@
\def\FLOWsplitnx{1}
\def\FLOWsplitny{1}
-\def\FLOWcharts%
+\def\FLOWcharts
{\dodoubleempty\doFLOWcharts}
%D While splitting, the following variables are available:
diff --git a/tex/context/base/m-chart.mkvi b/tex/context/base/m-chart.mkvi
index e94adeba2..cb6a1e8c8 100644
--- a/tex/context/base/m-chart.mkvi
+++ b/tex/context/base/m-chart.mkvi
@@ -30,19 +30,33 @@
% 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
+% \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
+
+\installcorenamespace {flowchart} % \def\??flch{@@flch} % chart
+\installcorenamespace {flowline} % \def\??flln{@@flln} % line
+\installcorenamespace {flowshape} % \def\??flsh{@@flsh} % shape
+\installcorenamespace {flowfocus} % \def\??flfc{@@flfc} % focus
+\installcorenamespace {flowsets} % \def\??flst{@@flst} % sets
+\installcorenamespace {flowsplit} % \def\??flsp{@@flsp} % split
+
+\installsimplecommandhandler \??flowchart {FLOWchart} \??flowchart % maybe just a setuphandler
+\installsimplecommandhandler \??flowline {FLOWline} \??flowline % maybe just a setuphandler
+\installsimplecommandhandler \??flowshape {FLOWshape} \??flowshape % maybe just a setuphandler
+\installsimplecommandhandler \??flowfocus {FLOWfocus} \??flowfocus % maybe just a setuphandler
+\installsimplecommandhandler \??flowsets {FLOWsets} \??flowsets % maybe just a setuphandler
+\installsimplecommandhandler \??flowsplit {FLOWsplit} \??flowsplit % maybe just a setuphandler
\let\setupFLOWcharts\setupFLOWchart
\let\setupFLOWlines \setupFLOWline
@@ -62,6 +76,7 @@
\c!labeloffset=.5\bodyfontsize,
\c!commentoffset=.5\bodyfontsize,
\c!exitoffset=\zeropoint,
+ % \c!split=\v!no,
% \c!maxwidth=,
% \c!maxheight=,
% \c!option=,
@@ -101,13 +116,17 @@
\c!offset=\FLOWshapeparameter\c!offset]
\setupFLOWsplit
- [\c!state=\v!stop,
- \c!marking=\v!on,
+ [\c!dx=0,
+ \c!dy=0,
% \c!command=,
% \c!before=,
% \c!after=,
\c!nx=3,
- \c!ny=3]
+ \c!ny=4]
+
+\unexpanded\def\beforeFLOWsplit{\FLOWsplitparameter\c!before}
+\unexpanded\def\afterFLOWsplit {\FLOWsplitparameter\c!after}
+\unexpanded\def\handleFLOWsplit{\FLOWsplitparameter\c!command}
\definecolor [FLOWfocuscolor] [s=.2]
\definecolor [FLOWlinecolor] [s=.5]
@@ -184,7 +203,7 @@
{\dodoubleempty\module_charts_process}
\def\module_charts_process[#name][#settings]%
- {\vbox\bgroup
+ {\bgroup % \vbox removed
\insidefloattrue
\dontcomplain
\setupFLOWchart[#settings]%
@@ -212,6 +231,7 @@
labeloffset = \number\dimexpr\FLOWchartparameter\c!labeloffset,
commentoffset = \number\dimexpr\FLOWchartparameter\c!commentoffset,
exitoffset = \number\dimexpr\FLOWchartparameter\c!exitoffset,
+ split = "\FLOWchartparameter\c!split",
},
shape = {
rulethickness = \number\dimexpr\FLOWshapeparameter\c!rulethickness,
@@ -236,9 +256,10 @@
set = {
},
split = {
- state = "\FLOWsplitparameter\c!state",
nx = \number\FLOWsplitparameter\c!nx,
ny = \number\FLOWsplitparameter\c!ny,
+ dx = \number\FLOWsplitparameter\c!dx,
+ dy = \number\FLOWsplitparameter\c!dy,
command = "",
marking = "\FLOWsplitparameter\c!marking",
before = "",
@@ -314,11 +335,14 @@
align=,
set=\setups{flowcell:text:place}]
+\def\FLOWx{\getvariable{flowcell:text}{x}} % compatibility (for Willi)
+\def\FLOWy{\getvariable{flowcell:text}{y}} % compatibility (for Willi)
+
% \c!background={\@@FLOWbackground,\FLOWoverlay},
\defineoverlay
- [flowcell:figure]
- [\overlayfigure{\getvariable{flowcell:text}{figure}}]
+ [flowcell:figure]
+ [\overlayfigure{\getvariable{flowcell:text}{figure}}]
\startsetups flowcell:text:place
\begingroup
@@ -387,35 +411,73 @@
\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:text:user
+% \setupframed
+% [flowcell:base]
+% [background=flowcell]
+% \definelayer
+% [flowcell]
+% [width=\namedframedparameter{flowcell:base}{width},
+% height=\namedframedparameter{flowcell:base}{height}]
+% \setlayerframed
+% [flowcell]
+% [preset=rightbottom,offset=-2.75ex]
+% [frame=off]
+% {\tx\FLOWx.\FLOWy}
+% \stopsetups
+%
+% % or:
%
-% \startsetups flowcell
-% \definelayer
-% [flowcell]
-% [width=\FLOWshapewidth,
-% height=\FLOWshapeheight]
-% \setlayerframed
-% [flowcell]
-% [preset=rightbottom,offset=1ex]
-% [frame=off]
-% {\tx(\FLOWx,\FLOWy)}
+% \setupframed
+% [flowcell:base]
+% [background={flowcell-1,flowcell-2}]
+%
+% \defineoverlay
+% [flowcell-1]
+% [\directsetup{flowcell-1}]
+%
+% \definelayer
+% [flowcell-2]
+% [width=\overlaywidth,
+% height=\overlayheight]
+%
+% \startsetups flowcell-1
+% \setlayerframed
+% [flowcell-2]
+% [preset=rightbottom,offset=-2.75ex]
+% [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
+% %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
+
+% \setupFLOWsplit
+% [nx=5,
+% ny=8,
+% dx=1,
+% dy=1,
+% command=\framed,
+% before=\page,
+% after=\page]
+%
+% \FLOWchart[demo] \page
+% \FLOWchart[demo][split=yes] \page
+% \FLOWchart[demo][x=1,y=1,nx=5,ny=8] \page
+% \FLOWchart[demo][x=1,y=9,nx=5,ny=10] \page
\protect
diff --git a/tex/context/base/m-database.mkiv b/tex/context/base/m-database.mkiv
index cef0aa815..01f84482a 100644
--- a/tex/context/base/m-database.mkiv
+++ b/tex/context/base/m-database.mkiv
@@ -17,11 +17,6 @@
\unprotect
-\def\c!first {first}
-\def\c!last {last}
-\def\c!quotechar {quotechar}
-\def\c!commentchar {commentchar}
-
\definenamespace
[db]
[type=module,
@@ -98,7 +93,7 @@
\protect
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{m-database.mkiv}
\starttext
diff --git a/tex/context/base/m-graph.mkiv b/tex/context/base/m-graph.mkiv
index db72927fb..8acbe1f8d 100644
--- a/tex/context/base/m-graph.mkiv
+++ b/tex/context/base/m-graph.mkiv
@@ -16,100 +16,76 @@
% the percent symbol. We also add a specifier when no one is given.
\startluacode
- local function strip(s)
- return "\\times10^{"..(s:gsub("%+*0*","")).."}"
+ local format, gsub, find, match = string.format, string.gsub, string.find, string.match
+
+ local simplify = true
+
+ local function strip(n,e)
+ -- get rid of e(0)
+ -- get rid of e(+*)
+ e = gsub(e,"^+","")
+ -- remove leading zeros
+ e = gsub(e,"^([+-]*)0+(%d)","%1%2")
+ if not simplify then
+ -- take it as it is
+ elseif n == "1" then
+ return format("10^{%s}",e)
+ end
+ return format("%s\\times10^{%s}",n,e)
end
+
function metapost.format_n(fmt,str)
- fmt = fmt:gsub("@","%%")
- local initial, format, final = fmt:match("^(.-)(%%.-[%a])(.-)$")
- if format then
- str = fmt:format(str)
- str = str:gsub("e(.-)$",strip)
- str = ("%s\\mathematics{%s}%s"):format(initial,str,final)
- elseif not fmt:find("%%") then
- str = ("%"..fmt):format(str)
- str = str:gsub("e(.-)$",strip)
- str = ("\\mathematics{%s}"):format(str)
+ fmt = gsub(fmt,"@","%%")
+ local initial, hasformat, final = match(fmt,"^(.-)(%%.-[%a])(.-)$")
+ if hasformat then
+ str = format(fmt,str)
+ str = gsub(str,"(.-)e(.-)$",strip)
+ str = format("%s\\mathematics{%s}%s",initial,str,final)
+ elseif not find(fmt,"%%") then
+ str = format("%"..fmt,str)
+ str = gsub(str,"(.-)e(.-)$",strip)
+ str = format("\\mathematics{%s}",str)
end
context(str)
end
\stopluacode
-\unexpanded\long\def\MPgraphformat#1#2{\ctxlua{metapost.format_n("#1","#2")}}
+\unexpanded\def\MPgraphformat#1#2{\ctxlua{metapost.format_n("#1","#2")}}
% We could also delegate parsing using lower level plugins.
-\startMPinclusions
- % input string ;
- % input marith ;
- input graph.mp ;
-
- vardef roundd(expr x, d) =
- if abs d > 4 :
- if d > 0 :
- x
- else :
- 0
- fi
- elseif d > 0 :
- save i ; i = floor x ;
- i + round(Ten_to[d]*(x-i))/Ten_to[d]
- else :
- round(x/Ten_to[-d])*Ten_to[-d]
- fi
- enddef ;
-
- Ten_to0 = 1 ;
- Ten_to1 = 10 ;
- Ten_to2 = 100 ;
- Ten_to3 = 1000 ;
- Ten_to4 = 10000 ;
-
- def sFe_base =
- enddef ;
-
- picture Fe_plus ; Fe_plus := btex + etex ;
-
- vardef format (expr f,x) = dofmt_.Feform_(f,x) enddef ;
- vardef Mformat (expr f,x) = dofmt_.Meform (f,x) enddef ;
- vardef formatstr (expr f,x) = dofmt_.Feform_(f,x) enddef ;
- vardef Mformatstr(expr f,x) = dofmt_.Meform(f,x) enddef ;
-
- vardef escaped_format(expr s) =
- "" for n=1 upto length(s) : &
- if ASCII substring (n,n+1) of s = 37 :
- "@"
- else :
- substring (n,n+1) of s
- fi
- endfor
- enddef ;
-
- vardef dofmt_@\#(expr f, x) =
- textext("\MPgraphformat{" & escaped_format(f) & "}{" & (if string x : x else: decimal x fi) & "}")
- enddef ;
-
- % vardef format(expr f, x) =
- % textext("\MPgraphformatN{"&escaped_format(f)&"}{"&(if string x : x else: decimal x fi)&"}")
- % enddef;
- % vardef Mformat(expr f, x) =
- % format(f,x)
- % enddef;
-
-\stopMPinclusions
+\startMPextensions
+ if unknown Fe_plus : picture Fe_plus ; Fe_plus := textext("+") ; fi ;
+ if unknown context_grap: input "mp-grap.mpiv" ; fi ;
+\stopMPextensions
\continueifinputfile{m-graph.mkiv}
\starttext
\startMPpage
-draw begingraph(3in,2in);
- gdraw "t:/metapost/grphdata/agepop91.d";
-endgraph;
+ label(format("@g","1e-8"), (0, 0)) ;
+ label(format("@g","1e+8"), (2cm, 0)) ;
+ label(format("@g","1e-10"), (0, -0.5cm)) ;
+ label(format("@g","1e+10"), (2cm,-0.5cm)) ;
+ label(format("@g","1e-12"), (0, -1.0cm)) ;
+ label(format("@g","1e+12"), (2cm,-1.0cm)) ;
+ label(format("@g","1e-0"), (0, -1.5cm)) ;
+ label(format("@g","1e+0"), (2cm,-1.5cm)) ;
+ label(format("@g","1"), (0, -2.0cm)) ;
+ label(format("@g","1"), (2cm,-2.0cm)) ;
+ label(format("@g","1e-102"),(0, -2.5cm)) ;
+ label(format("@g","1e+102"),(2cm,-2.5cm)) ;
\stopMPpage
% \startMPpage
% draw begingraph(3in,2in);
+% gdraw "t:/metapost/grphdata/agepop91.d";
+% endgraph;
+% \stopMPpage
+
+% \startMPpage
+% draw begingraph(3in,2in);
% gdraw "agepop91.d" plot btex $\bullet$ etex;
% endgraph;
% \stopMPpage
diff --git a/tex/context/base/m-ipsum.mkiv b/tex/context/base/m-ipsum.mkiv
new file mode 100644
index 000000000..1c5901d86
--- /dev/null
+++ b/tex/context/base/m-ipsum.mkiv
@@ -0,0 +1,198 @@
+%D \module
+%D [ file=m-ipsum,
+%D version=2012.07.19,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Ipsum,
+%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 After some discussing on the mailing list I made this example of
+%D an implementation. Of course there can be alternatives as it's a
+%D nice exercise in module writing.
+
+\startluacode
+
+local patterns = lpeg.patterns
+
+local variables = interfaces.variables
+local v_random = variables.random
+
+local lowercase = characters.lower
+
+local ipsum = { }
+moduledata.ipsum = ipsum
+
+local data = { }
+
+local function getfiledata(settings)
+ local filename = settings.filename or ""
+ local filedata = data[filename]
+ if not filedata then
+ local text = resolvers.loadtexfile(filename) or ""
+ local paragraphs = lpeg.match(patterns.paragraphs,text) or { }
+ local sentences = lpeg.match(patterns.sentences, text) or { }
+ local words = lpeg.match(patterns.words, text) or { }
+ for i=1,#words do
+ words[i] = lowercase(words[i])
+ end
+ filedata = {
+ -- [variables.paragraphs] = paragraphs,
+ [variables.paragraph] = paragraphs,
+ [variables.lines] = sentences,
+ [variables.line] = sentences,
+ [variables.words] = words,
+ [variables.word] = words,
+ }
+ -- inspect(filedata)
+ data[filename] = filedata
+ end
+ local d = filedata[settings.alternative or v_paragraph] or filedata[v_paragraph] or { }
+ local nd = #d
+ local n = settings.n
+ if n ~= v_random then
+ n = tonumber(n) or 0
+ if n == 0 then
+ n = nd
+ end
+ end
+ return d, n, nd
+end
+
+function moduledata.ipsum.typeset(settings)
+ local d, n, nd = getfiledata(settings)
+ if nd > 0 then
+ context(settings.before)
+ if n == v_random then
+ context(settings.left)
+ context(d[math.random(1,nd)])
+ context(settings.right)
+ else
+ for i=1,n do
+ context(settings.left)
+ context(d[i])
+ context(settings.right)
+ if i < n then
+ context(settings.inbetween)
+ end
+ end
+ end
+ context(settings.after)
+ end
+end
+
+function moduledata.ipsum.direct(settings)
+ local d, n, nd = getfiledata(settings)
+ if nd == 0 then
+ -- nothing
+ elseif n == v_random then
+ context(d[math.random(1,nd)])
+ else
+ for i=1,n do
+ context(d[i])
+ if i < n then
+ context(settings.separator)
+ end
+ end
+ end
+end
+
+\stopluacode
+
+\unprotect
+
+\installnamespace {ipsum}
+
+\installcommandhandler \????ipsum {ipsum} \????ipsum
+
+\setupipsum
+ [\c!file=lorem,
+ \c!alternative=\v!paragraph,
+ %\c!language=,
+ %\c!styl=,
+ %\c!color=,
+ \c!n=0,
+ \c!left=,
+ \c!right=,
+ \c!before=,
+ \c!after=,
+ \c!separator=,
+ \c!inbetween=]
+
+\installactionhandler{ipsum} % grouped
+
+\startsetups[handler:action:ipsum]
+ \useipsumstyleandcolor\c!style\c!color
+ \uselanguageparameter\ipsumparameter
+ \ctxlua{moduledata.ipsum.typeset {
+ alternative = "\ipsumparameter\c!alternative",
+ filename = "\ipsumparameter\c!file",
+ n = "\ipsumparameter\c!n",
+ left = "\luaescapestring{\ipsumparameter\c!left}",
+ right = "\luaescapestring{\ipsumparameter\c!right}",
+ before = "\luaescapestring{\ipsumparameter\c!before}",
+ after = "\luaescapestring{\ipsumparameter\c!after}",
+ inbetween = "\luaescapestring{\ipsumparameter\c!inbetween}",
+ }}
+\stopsetups
+
+\def\directipsum#1% only one argument, expanded
+ {\ctxlua{moduledata.ipsum.typeset {
+ alternative = "\namedipsumparameter{#1}\c!alternative",
+ filename = "\namedipsumparameter{#1}\c!file",
+ n = "\namedipsumparameter{#1}\c!n",
+ separator = "\luaescapestring{\ipsumparameter\c!separator}",
+ }}
+}
+
+\protect
+
+\continueifinputfile{m-ipsum.mkiv}
+
+\setupbodyfont[dejavu,11pt]
+
+\starttext
+
+ \ipsum[alternative=paragraph,before=\blank,after=\blank,language=la]
+
+ \ipsum[alternative=lines,n=2,right=\par,before=\blank,after=\blank,language=la]
+
+ \ipsum[alternative=lines,n=random,before=\blank,after=\blank,language=la]
+
+ \ipsum[alternative=lines,before=\startitemize,after=\stopitemize,left=\startitem,right=\stopitem,language=la]
+
+ \ipsum[alternative=words,left=(,right=),inbetween=\space,language=la]
+
+ \page
+
+ \defineipsum
+ [ward]
+ [file=ward,
+ before=\blank,
+ after=\blank]
+
+ \defineipsum
+ [ward:itemize]
+ [ward]
+ [alternative=lines,
+ before={\startitemize[packed]},
+ after=\stopitemize,
+ left=\startitem,
+ right=\stopitem]
+
+ \defineipsum
+ [ward:title]
+ [ward]
+ [alternative=lines,
+ n=random]
+
+ \subject{\directipsum{ward:title}}
+
+ \ipsum[ward]
+ \ipsum[ward:itemize]
+
+\stoptext
diff --git a/tex/context/base/m-json.mkiv b/tex/context/base/m-json.mkiv
new file mode 100644
index 000000000..329aa0f31
--- /dev/null
+++ b/tex/context/base/m-json.mkiv
@@ -0,0 +1,30 @@
+%D \module
+%D [ file=m-json,
+%D version=2012.08.03,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Json,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module is a side effect of looking into json. Currently there are
+%D only a few helpers:
+%D
+%D \starttyping
+%D moduledata.json.tolua (str)
+%D moduledata.json.tostring(val)
+%D \stoptyping
+%D
+%D Nothing spectacular but maybe handy to have around.
+
+\startmodule [json]
+
+% check for: utilities.json
+
+\registerctxluafile{util-jsn}{}
+
+\stopmodule
diff --git a/tex/context/base/m-morse.mkvi b/tex/context/base/m-morse.mkvi
index aba83bb2d..6082d588a 100644
--- a/tex/context/base/m-morse.mkvi
+++ b/tex/context/base/m-morse.mkvi
@@ -228,16 +228,16 @@ end
\def\MorseSpace {\hskip7\dimexpr\MorseWidth\relax}
\def\MorseUnknown #text{[\detokenize{#text}]}
-\def\MorseCode #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es,true)}}
-\def\MorseString #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es)}}
-\def\MorseFile #text{\ctxlua{moduledata.morse.filetomorse("#text")}}
-\def\MorseTable {\ctxlua{moduledata.morse.showtable()}}
+\unexpanded\def\MorseCode #text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es,true)}}
+\unexpanded\def\MorseString#text{\ctxlua{moduledata.morse.tomorse(\!!bs#text\!!es)}}
+\unexpanded\def\MorseFile #text{\ctxlua{moduledata.morse.filetomorse("#text")}}
+\unexpanded\def\MorseTable {\ctxlua{moduledata.morse.showtable()}}
-\let\Morse \MorseString
+\let\Morse \MorseString
\protect
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{m-morse.mkiv}
\starttext
diff --git a/tex/context/base/supp-fun.mkiv b/tex/context/base/m-oldfun.mkiv
index 33bee0306..1c5a1d29d 100644
--- a/tex/context/base/supp-fun.mkiv
+++ b/tex/context/base/m-oldfun.mkiv
@@ -1,5 +1,5 @@
%D \module
-%D [ file=supp-fun,
+%D [ file=m-oldfun, % was: supp-fun
%D version=1995.10.10,
%D title=\CONTEXT\ Support Macros,
%D subtitle=Fun Stuff,
@@ -119,7 +119,7 @@
\let\globaldropcaps\global % will be an option, but on by default
-\def\localdropcaps{\let\globaldropcaps\relax}
+\unexpanded\def\localdropcaps{\let\globaldropcaps\relax}
\chardef\DroppedStatus = 0 % 0=done 1=starting 2=doing 3=error
\chardef\DropMode = 0 % 1 == marginhang
@@ -128,7 +128,7 @@
\let\keeplinestogether\gobbleoneargument
\fi
-\def\DroppedCaps#1#2#3#4#5#6#7% does not yet handle accented chars
+\unexpanded\def\DroppedCaps#1#2#3#4#5#6#7% does not yet handle accented chars
{\defconvertedargument\asciia{#7}%
\defconvertedcommand \asciib{\DroppedString}%
\doifinstringelse\asciia\asciib
@@ -222,10 +222,10 @@
\newcount\lastprevgraf
\newcount\droppedlines
-\def\CheckDroppedCaps
+\unexpanded\def\CheckDroppedCaps
{\global\lastprevgraf\prevgraf}
-\def\AutoDroppedCaps % will be proper core stuff since it
+\unexpanded\def\AutoDroppedCaps % will be proper core stuff since it
{\globaldropcaps\chardef\DroppedStatus\plusone
\global\lastprevgraf\zerocount
\global\droppedlines\zerocount
@@ -234,10 +234,10 @@
\let\AutoDroppedNext\relax
\ifx\AutoDroppedCapsCommand\undefined
- \def\AutoDroppedCapsCommand{\NiceDroppedCaps{}{SerifBold}{.125em}{3}}
+ \unexpanded\def\AutoDroppedCapsCommand{\NiceDroppedCaps{}{SerifBold}{.125em}{3}}
\fi
-\def\doAutoDroppedCaps
+\unexpanded\def\doAutoDroppedCaps
{\ifcase\DroppedStatus % done
\let\next\relax
\or % starting
@@ -287,7 +287,7 @@
%D the second command scales the font to a nice 2.5 times the
%D line height, a value that gives a pleasant grayness.
-\def\DoLineDroppedCaps#1#2#3#4#5% compensation command font offset lines
+\unexpanded\def\DoLineDroppedCaps#1#2#3#4#5% compensation command font offset lines
{\scratchcounter#5%
\advance\scratchcounter \minusone
\scratchdimen\scratchcounter\baselineskip
@@ -296,10 +296,10 @@
\DroppedCaps{#2}{#3}\TheNormalizedFontSize{#4}
{\scratchcounter\baselineskip}{#5}}
-\def\LineDroppedCaps% command font offset lines
+\unexpanded\def\LineDroppedCaps% command font offset lines
{\DoLineDroppedCaps{\strutht}}
-\def\NiceDroppedCaps% command font offset lines
+\unexpanded\def\NiceDroppedCaps% command font offset lines
{\DoLineDroppedCaps{.5\baselineskip}}
%D \macros
@@ -337,7 +337,7 @@
%D with that. A workaround is rather trivial but obscures the
%D principles used.
-\def\TreatFirstLine#1#2#3#4% before, after, first, next
+\unexpanded\def\TreatFirstLine#1#2#3#4% before, after, first, next
{\leavevmode
\bgroup
\forgetall
@@ -428,7 +428,7 @@
%D \getbuffer complete we also offer a very simple one
%D character alternative, that is not that hard to understand:
-\def\TreatFirstCharacter#1#2% command, character
+\unexpanded\def\TreatFirstCharacter#1#2% command, character
{{#1{#2}}}
%D A previous paragraph started with:
@@ -440,7 +440,7 @@
%D
%D The next hack deals with vertical stacking.
-\def\StackCharacters#1#2#3#4% sequence vsize vskip command
+\unexpanded\def\StackCharacters#1#2#3#4% sequence vsize vskip command
{\vbox #2
{\forgetall
\baselineskip\zeropoint
@@ -531,10 +531,10 @@
%D
%D These are implemented using an auxilliary macro:
-\def\NormalizeFontHeight{\NormalizeFontSize\ht}
-\def\NormalizeFontWidth {\NormalizeFontSize\wd}
+\unexpanded\def\NormalizeFontHeight{\NormalizeFontSize\ht}
+\unexpanded\def\NormalizeFontWidth {\NormalizeFontSize\wd}
-\def\NormalizeFontSize#1#2#3#4#5%
+\unexpanded\def\NormalizeFontSize#1#2#3#4#5%
{\bgroup
\dimen0=#4% #4 can be \ht0 or so
\setbox0\hbox{\definedfont[#5 at 5pt]#3}% 10pt
@@ -557,7 +557,7 @@
%D Extra:
-\def\WidthSpanningText#1#2#3% text width font
+\unexpanded\def\WidthSpanningText#1#2#3% text width font
{\hbox{\NormalizeFontWidth\temp{#1}{#2}{#3}\temp\the\everydefinedfont#1}}
%D Consider for instance:
@@ -642,7 +642,7 @@
% #1 width #2 height #3 font #4 size #5 step #6 interlinie #7 text
-\long\def\FittingText#1#2#3#4#5#6#7%
+\unexpanded\def\FittingText#1#2#3#4#5#6#7%
{\bgroup
\forgetall
\dontcomplain
@@ -681,11 +681,9 @@
\unvbox\scratchbox
\egroup}
-%D New:
-
% \font width gap font spec text
-\def\NormalizeFontWidthSpread#1#2#3#4#5#6%
+\unexpanded\def\NormalizeFontWidthSpread#1#2#3#4#5#6%
{\global\setfalse\NFSpread
\scratchdimen#3%
\scratchdimen-.5\scratchdimen
@@ -704,10 +702,10 @@
\definefont[\strippedcsname#1][#4 #5]%
\fi}
-\def\SpreadGapText#1#2%
+\unexpanded\def\SpreadGapText#1#2%
{{\def\+{\kern#1}#2}}
-\def\GapText#1#2#3#4#5% width distance font spec title
+\unexpanded\def\GapText#1#2#3#4#5% width distance font spec title
{\bgroup
\NormalizeFontWidthSpread\DummyFont{#1}{#2}{#3}{#4}{#5}%
\DummyFont\setupspacing\SpreadGapText{#2}{#5}\endgraf
diff --git a/tex/context/base/supp-num.mkiv b/tex/context/base/m-oldnum.mkiv
index be0df026d..efc0af472 100644
--- a/tex/context/base/supp-num.mkiv
+++ b/tex/context/base/m-oldnum.mkiv
@@ -1,5 +1,5 @@
%D \module
-%D [ file=supp-num,
+%D [ file=m-oldnum, % was: supp-num
%D version=1998.05.15,
%D title=\CONTEXT\ Support Macros,
%D subtitle=Numbers,
diff --git a/tex/context/base/m-pstricks.lua b/tex/context/base/m-pstricks.lua
index 7f795feac..b151e313a 100644
--- a/tex/context/base/m-pstricks.lua
+++ b/tex/context/base/m-pstricks.lua
@@ -39,12 +39,12 @@ local template = [[
\stoptext
]]
-local modules = { }
+local loaded = { }
local graphics = 0
function moduledata.pstricks.usemodule(names)
for name in gmatch(names,"([^%s,]+)") do
- modules[#modules+1] = format([[\readfile{%s}{}{}]],name)
+ loaded[#loaded+1] = format([[\readfile{%s}{}{}]],name)
end
end
@@ -55,10 +55,10 @@ function moduledata.pstricks.process(n)
local tmpfile = name .. ".tmp"
local epsfile = name .. ".ps"
local pdffile = name .. ".pdf"
- local modules = concat(modules,"\n")
+ local loaded = concat(loaded,"\n")
os.remove(epsfile)
os.remove(pdffile)
- io.savedata(tmpfile,format(template,modules,data))
+ io.savedata(tmpfile,format(template,loaded,data))
os.execute(format("mtxrun --script texexec %s --once --dvips",tmpfile))
if lfs.isfile(epsfile) then
os.execute(format("ps2pdf %s %s",epsfile,pdffile))
diff --git a/tex/context/base/m-spreadsheet.lua b/tex/context/base/m-spreadsheet.lua
new file mode 100644
index 000000000..30980684f
--- /dev/null
+++ b/tex/context/base/m-spreadsheet.lua
@@ -0,0 +1,331 @@
+if not modules then modules = { } end modules ['m-spreadsheet'] = {
+ version = 1.001,
+ comment = "companion to m-spreadsheet.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local byte, format, gsub, find = string.byte, string.format, string.gsub, string.find
+local R, P, S, C, V, Cs, Cc, Ct, Cg, Cf, Carg = lpeg.R, lpeg.P, lpeg.S, lpeg.C, lpeg.V, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cg, lpeg.Cf, lpeg.Carg
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local setmetatable, loadstring, next, tostring, tonumber,rawget = setmetatable, loadstring, next, tostring, tonumber, rawget
+
+local context = context
+
+local splitthousands = utilities.parsers.splitthousands
+local variables = interfaces.variables
+
+local v_yes = variables.yes
+
+moduledata = moduledata or { }
+
+local spreadsheets = { }
+moduledata.spreadsheets = spreadsheets
+
+local data = {
+ -- nothing yet
+}
+
+local settings = {
+ period = ".",
+ comma = ",",
+}
+
+spreadsheets.data = data
+spreadsheets.settings = settings
+
+local defaultname = "default"
+local stack = { }
+local current = defaultname
+
+local d_mt ; d_mt = {
+ __index = function(t,k)
+ local v = { }
+ setmetatable(v,d_mt)
+ t[k] = v
+ return v
+ end,
+}
+
+local s_mt ; s_mt = {
+ __index = function(t,k)
+ local v = settings[k]
+ t[k] = v
+ return v
+ end,
+}
+
+function spreadsheets.setup(t)
+ for k, v in next, t do
+ settings[k] = v
+ end
+end
+
+local function emptydata(name,settings)
+ local data = { }
+ local specifications = { }
+ local settings = settings or { }
+ setmetatable(data,d_mt)
+ setmetatable(specifications,d_mt)
+ setmetatable(settings,s_mt)
+ return {
+ name = name,
+ data = data,
+ maxcol = 0,
+ maxrow = 0,
+ settings = settings,
+ temp = { }, -- for local usage
+ specifications = specifications,
+ }
+end
+
+function spreadsheets.reset(name)
+ if not name or name == "" then name = defaultname end
+ data[name] = emptydata(name,data[name] and data[name].settings)
+end
+
+function spreadsheets.start(name,s)
+ if not name or name == "" then
+ name = defaultname
+ end
+ if not s then
+ s = { }
+ end
+ table.insert(stack,current)
+ current = name
+ if data[current] then
+ setmetatable(s,s_mt)
+ data[current].settings = s
+ else
+ data[current] = emptydata(name,s)
+ end
+end
+
+function spreadsheets.stop()
+ current = table.remove(stack)
+end
+
+spreadsheets.reset()
+
+local offset = byte("A") - 1
+
+local function assign(s,n)
+ return format("moduledata.spreadsheets.data['%s'].data[%s]",n,byte(s)-offset)
+end
+
+function datacell(a,b,...)
+ local n = 0
+ if b then
+ local t = { a, b, ... }
+ for i=1,#t do
+ n = n * (i-1) * 26 + byte(t[i]) - offset
+ end
+ else
+ n = byte(a) - offset
+ end
+ return format("dat[%s]",n)
+end
+
+local function checktemplate(s)
+ if find(s,"%%") then
+ -- normal template
+ return s
+ elseif find(s,"@") then
+ -- tex specific template
+ return gsub(s,"@","%%")
+ else
+ -- tex specific quick template
+ return "%" .. s
+ end
+end
+
+local quoted = Cs(patterns.unquoted)
+local spaces = patterns.whitespace^0
+local cell = C(R("AZ"))^1 / datacell * (Cc("[") * (R("09")^1) * Cc("]") + #P(1))
+
+-- A nasty aspect of lpeg: Cf ( spaces * Cc("") * { "start" ... this will create a table that will
+-- be reused, so we accumulate!
+
+local pattern = Cf ( spaces * Ct("") * { "start",
+ start = V("value") + V("set") + V("format") + V("string") + V("code"),
+ value = Cg(P([[=]]) * spaces * Cc("kind") * Cc("value")) * V("code"),
+ set = Cg(P([[!]]) * spaces * Cc("kind") * Cc("set")) * V("code"),
+ format = Cg(P([[@]]) * spaces * Cc("kind") * Cc("format")) * spaces * Cg(Cc("template") * Cs(quoted/checktemplate)) * V("code"),
+ string = Cg(#S([["']]) * Cc("kind") * Cc("string")) * Cg(Cc("content") * quoted),
+ code = spaces * Cg(Cc("code") * Cs((cell + P(1))^0)),
+}, rawset)
+
+local functions = { }
+spreadsheets.functions = functions
+
+function functions._s_(row,col,c,f,t)
+ local r = 0
+ if f and t then -- f..t
+ -- ok
+ elseif f then -- 1..f
+ f, t = 1, f
+ else
+ f, t = 1, row - 1
+ end
+ for i=f,t do
+ local ci = c[i]
+ if type(ci) == "number" then
+ r = r + c[i]
+ end
+ end
+ return r
+end
+
+functions.fmt= string.tformat
+
+local template = [[
+ local _m_ = moduledata.spreadsheets
+ local dat = _m_.data['%s'].data
+ local tmp = _m_.temp
+ local fnc = _m_.functions
+ local row = %s
+ local col = %s
+ function fnc.sum(...) return fnc._s_(row,col,...) end
+ local sum = fnc.sum
+ local fmt = fnc.fmt
+ return %s
+]]
+
+-- to be considered: a weak cache
+
+local function propername(name)
+ if name ~= "" then
+ return name
+ elseif current ~= "" then
+ return current
+ else
+ return defaultname
+ end
+end
+
+-- if name == "" then name = current if name == "" then name = defaultname end end
+
+local function execute(name,r,c,str)
+ if str ~= "" then
+ local d = data[name]
+ if c > d.maxcol then
+ d.maxcol = c
+ end
+ if r > d.maxrow then
+ d.maxrow = r
+ end
+ local specification = lpegmatch(pattern,str,1,name)
+ d.specifications[c][r] = specification
+ local kind = specification.kind
+ if kind == "string" then
+ return specification.content or ""
+ else
+ local code = specification.code
+ if code and code ~= "" then
+ code = format(template,name,r,c,code or "")
+ local result = loadstring(code) -- utilities.lua.strippedloadstring(code,true) -- when tracing
+ result = result and result()
+ if type(result) == "function" then
+ result = result()
+ end
+ if type(result) == "number" then
+ d.data[c][r] = result
+ end
+ if not result then
+ -- nothing
+ elseif kind == "set" then
+ -- no return
+ elseif kind == "format" then
+ return format(specification.template,result)
+ else
+ return result
+ end
+ end
+ end
+ end
+end
+
+function spreadsheets.set(name,r,c,str)
+ name = propername(name)
+ execute(name,r,c,str)
+end
+
+function spreadsheets.get(name,r,c,str)
+ name = propername(name)
+ local dname = data[name]
+ if not dname then
+ -- nothing
+ elseif not str or str == "" then
+ context(dname.data[c][r] or 0)
+ else
+ local result = execute(name,r,c,str)
+ if result then
+-- if type(result) == "number" then
+-- dname.data[c][r] = result
+-- result = tostring(result)
+-- end
+ local settings = dname.settings
+ local split = settings.split
+ local period = settings.period
+ local comma = settings.comma
+ if split == v_yes then
+ result = splitthousands(result)
+ end
+ if period == "" then period = nil end
+ if comma == "" then comma = nil end
+ result = gsub(result,".",{ ["."] = period, [","] = comma })
+ context(result)
+ end
+ end
+end
+
+function spreadsheets.doifelsecell(name,r,c)
+ name = propername(name)
+ local d = data[name]
+ local d = d and d.data
+ local r = d and rawget(d,r)
+ local c = r and rawget(r,c)
+ commands.doifelse(c)
+end
+
+local function simplify(name)
+ name = propername(name)
+ local data = data[name]
+ if data then
+ data = data.data
+ local temp = { }
+ for k, v in next, data do
+ local t = { }
+ temp[k] = t
+ for kk, vv in next, v do
+ if type(vv) == "function" then
+ t[kk] = "<function>"
+ else
+ t[kk] = vv
+ end
+ end
+ end
+ return temp
+ end
+end
+
+local function serialize(name)
+ local s = simplify(name)
+ if s then
+ return table.serialize(s,name)
+ else
+ return format("<unknown spreadsheet %q>",name)
+ end
+end
+
+spreadsheets.simplify = simplify
+spreadsheets.serialize = serialize
+
+function spreadsheets.inspect(name)
+ inspect(serialize(name))
+end
+
+function spreadsheets.tocontext(name)
+ context.tocontext(simplify(name))
+end
diff --git a/tex/context/base/m-spreadsheet.mkiv b/tex/context/base/m-spreadsheet.mkiv
index 839214096..ed9a92d05 100644
--- a/tex/context/base/m-spreadsheet.mkiv
+++ b/tex/context/base/m-spreadsheet.mkiv
@@ -13,192 +13,139 @@
%D This is an experimental follow up on discussion on the mailing list.
-\startluacode
-local byte, format = string.byte, string.format
-local R, P, C, Cs, Cc, Carg, lpegmatch = lpeg.R, lpeg.P, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.match
-
-local spreadsheets = { }
-moduledata.spreadsheets = spreadsheets
-
-local data = { }
-spreadsheets.data = data
-
-local stack, current = { }, "default"
-
-local mt ; mt = {
- __index = function(t,k)
- local v = { }
- setmetatable(v,mt)
- t[k] = v
- return v
- end,
-}
-
-function spreadsheets.reset(name)
- if not name or name == "" then name = "default" end
- local d = { }
- setmetatable(d,mt)
- data[name] = d
-end
-
-function spreadsheets.start(name)
- if not name or name == "" then name = "default" end
- table.insert(stack,current)
- current = name
- if not data[current] then
- local d = { }
- setmetatable(d,mt)
- data[current] = d
- end
-end
-
-function spreadsheets.stop()
- current = table.remove(stack)
-end
-
-spreadsheets.reset()
-
-local offset = byte("A") - 1
-
-local function assign(s,n)
- return format("moduledata.spreadsheets.data['%s'][%s]",n,byte(s)-offset)
-end
-
--------- datacell(name,a,b,...)
-function datacell(a,b,...)
- local n = 0
- if b then
- local t = { a, b, ... }
- for i=1,#t do
- n = n * (i-1) * 26 + byte(t[i]) - offset
- end
- else
- n = byte(a) - offset
- end
- -- return format("dat['%s'][%s]",name,n)
- return format("dat[%s]",n)
-end
-
------ cell = (Carg(1) * C(R("AZ"))^1) / datacell * (Cc("[") * (R("09")^1) * Cc("]") + #P(1))
-local cell = C(R("AZ"))^1 / datacell * (Cc("[") * (R("09")^1) * Cc("]") + #P(1))
-local pattern = Cs(Cc("return ") * (cell + P(1))^0)
-
-local functions = { }
-spreadsheets.functions = functions
-
-function functions.sum(c,f,t)
- if f and t then
- local r = 0
- for i=f,t do
- r = r + c[i]
- end
- return r
- else
- return 0
- end
-end
-
-function functions.fmt(pattern,n)
- return format("%"..pattern,n)
-end
-
-local template = [[
- local spr = moduledata.spreadsheets.functions
- local dat = moduledata.spreadsheets.data['%s']
- local sum = spr.sum
- local fmt = spr.fmt
- %s
-]]
-
-local function execute(name,r,c,str)
- if name == "" then name = current if name == "" then name = "default" end end
- str = lpegmatch(pattern,str,1,name)
- str = format(template,name,str)
- -- print(str)
- local result = loadstring(str)
- result = result and result() or 0
- data[name][c][r] = result
- return result
-end
-
-function spreadsheets.set(name,r,c,str)
- if name == "" then name = current if name == "" then name = "default" end end
- execute(name,r,c,str)
-end
-
-function spreadsheets.get(name,r,c,str)
- if name == "" then name = current if name == "" then name = "default" end end
- if not str or str == "" then
- context(data[name][c][r] or 0)
- else
- local result = execute(name,r,c,str)
- if result then
- if type(result) == "number" then
- data[name][c][r] = result
- end
- context(result)
- end
- end
-end
-
-function spreadsheets.doifelsecell(name,r,c)
- if name == "" then name = current if name == "" then name = "default" end end
- local d = data[name]
- commands.testcase(d and d[c][r])
-end
-
-function spreadsheets.show(name)
- if name == "" then name = current if name == "" then name = "default" end end
- table.print(data[name],name)
-end
-\stopluacode
+\registerctxluafile{m-spreadsheet}{1.001}
\unprotect
% todo: get(...) set(..) ctx(...)
-\unexpanded\def\resetspreadsheet {\dosingleempty\doresetspreadsheet}
-\unexpanded\def\doresetspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.reset("#1")}}
-\unexpanded\def\startspreadsheet {\dosingleempty\dostartspreadsheet}
-\unexpanded\def\dostartspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.start("#1")}}
-\unexpanded\def\stopspreadsheet {\ctxlua{moduledata.spreadsheets.stop()}}
-\unexpanded\def\showspreadsheet {\dosingleempty\doshowspreadsheet}
-\unexpanded\def\doshowspreadsheet [#1]{\ctxlua{moduledata.spreadsheets.show("#1")}}
-\unexpanded\def\getspreadsheet {\dosingleempty\dogetspreadsheet}
-\unexpanded\def\dosetspreadsheet [#1]#2#3#4{\ctxlua{moduledata.spreadsheets.set ("#1",\number#2,\number#3,"#4")}}
-\unexpanded\def\setspreadsheet {\dosingleempty\dosetspreadsheet}
-\unexpanded\def\dogetspreadsheet [#1]#2#3#4{\ctxlua{moduledata.spreadsheets.get ("#1",\number#2,\number#3,"#4")}}
-\unexpanded\def\doifelsespreadsheetcell {\dosingleempty\dodoifelsespreadsheetcell}
-\unexpanded\def\dodoifelsespreadsheetcell[#1]#2#3{\ctxlua{moduledata.spreadsheets.doifelsecell("#1","#2","#3")}}
-
-\def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}}
-\def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}}
+\installcorenamespace{spreadsheet}
+
+\installcommandhandler \??spreadsheet {spreadsheet} \??spreadsheet
+
+\appendtoks
+ \ctxlua{moduledata.spreadsheets.setup{ % global !
+ period = "\spreadsheetparameter\c!period",
+ comma = "\spreadsheetparameter\c!comma",
+ split = "\spreadsheetparameter\c!split",
+ }}%
+\to \everysetupspreadsheet
+
+\setupspreadsheet
+ [%\c!comma=,
+ %\c!period=,
+ \c!split=\v!no]
+
+\unexpanded\def\resetspreadsheet
+ {\dosingleempty\module_spreadsheet_reset}
+
+\unexpanded\def\module_spreadsheet_reset[#1]%
+ {\ctxlua{moduledata.spreadsheets.reset("#1")}}
+
+\unexpanded\def\startspreadsheet
+ {\dosingleempty\module_spreadsheet_start}
+
+\unexpanded\def\module_spreadsheet_start[#1]%
+ {\pushmacro\currentspreadsheet
+ \edef\currentspreadsheet{#1}%
+ \checkspreadsheetparent
+ \edef\m_spreadsheet_period{\spreadsheetparameter\c!period}%
+ \edef\m_spreadsheet_comma {\spreadsheetparameter\c!comma}%
+ \ctxlua{moduledata.spreadsheets.start("#1", {
+ period = \!!bs\detokenize\expandafter{\m_spreadsheet_period}\!!es,
+ comma = \!!bs\detokenize\expandafter{\m_spreadsheet_comma}\!!es,
+ split = "\spreadsheetparameter\c!split",
+ })}}
+
+\unexpanded\def\stopspreadsheet
+ {\ctxlua{moduledata.spreadsheets.stop()}%
+ \popmacro\currentspreadsheet}
+
+\unexpanded\def\showspreadsheet
+ {\dosingleempty\module_spreadsheet_show}
+
+\unexpanded\def\module_spreadsheet_show[#1]%
+ {\ctxlua{moduledata.spreadsheets.tocontext("#1")}}
+
+\unexpanded\def\inspectspreadsheet
+ {\dosingleempty\module_spreadsheet_inspect}
+
+\unexpanded\def\module_spreadsheet_inspect[#1]%
+ {\ctxlua{moduledata.spreadsheets.inspect("#1")}}
+
+\unexpanded\def\setspreadsheet
+ {\dosingleempty\module_spreadsheet_set}
+
+\unexpanded\def\module_spreadsheet_set[#1]#2#3#4%
+ {\ctxlua{moduledata.spreadsheets.set("#1",\number#2,\number#3,"#4")}}
+
+\unexpanded\def\getspreadsheet
+ {\dosingleempty\module_spreadsheet_get}
+
+\unexpanded\def\module_spreadsheet_get[#1]#2#3#4%
+ {\ctxlua{moduledata.spreadsheets.get("#1",\number#2,\number#3,"#4")}}
+
+\unexpanded\def\doifelsespreadsheetcell
+ {\dosingleempty\module_spreadsheet_doifelse_cell}
+
+\unexpanded\def\module_spreadsheet_doifelse_cell[#1]#2#3%
+ {\ctxlua{moduledata.spreadsheets.doifelsecell("#1",\number#2,\number#3)}}
+
+\ifdefined\tblrow
+
+ \def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}}
+ \def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\tblrow+1,\number\tblcol,\!!bs#1\!!es)}}
+
+\else
+
+ \def\TABLEsetspreadsheet#1{\ctxlua{moduledata.spreadsheets.set("",\number\c_tabl_ntb_row+1,\number\c_tabl_ntb_col,\!!bs#1\!!es)}}
+ \def\TABLEgetspreadsheet#1{\ctxlua{moduledata.spreadsheets.get("",\number\c_tabl_ntb_row+1,\number\c_tabl_ntb_col,\!!bs#1\!!es)}}
+
+\fi
\appendtoks
- \resetspreadsheet
+ \module_spreadsheet_reset[\currentspreadsheet]%
\let\setspr\TABLEsetspreadsheet
\let\getspr\TABLEgetspreadsheet
\to \everyTABLEpass
\unexpanded\def\startspreadsheettable % quick and dirty
- {\dosingleempty\dostartspreadsheettable}
+ {\dodoubleempty\module_spreadsheet_start_table}
-\unexpanded\def\dostartspreadsheettable[#1]%
+\unexpanded\def\module_spreadsheet_start_table[#1][#2]%
{\bgroup
- \startspreadsheet[#1]%%
- \def\startrow{\bTR}%
- \def\stoprow {\eTR}%
- \def\startcell##1\stopcell{\bTD\getspr{##1}\eTD}%
- \bTABLE[\c!align=flushright]}
+ \let\startrow \module_spreadsheet_row_start
+ \let\stoprow \module_spreadsheet_row_stop
+ \let\startcell\module_spreadsheet_cell_start
+ \let\stopcell \module_spreadsheet_cell_stop
+ \doifassignmentelse{#1}
+ {\module_spreadsheet_start
+ \bTABLE[\c!align=\v!flushright,#1]}
+ {\module_spreadsheet_start[#1]%
+ \bTABLE[\c!align=\v!flushright,#2]}}
\unexpanded\def\stopspreadsheettable
{\eTABLE
\stopspreadsheet
\egroup}
+\unexpanded\def\module_spreadsheet_row_start{\bTR}
+\unexpanded\def\module_spreadsheet_row_stop {\eTR}
+
+\unexpanded\def\module_spreadsheet_cell_start
+ {\doifnextoptionalelse\module_spreadsheet_cell_start_yes\module_spreadsheet_cell_start_nop}
+
+\unexpanded\def\module_spreadsheet_cell_start_yes[#1]#2\stopcell
+ {\bTD[#1]\getspr{#2}\eTD}
+
+\unexpanded\def\module_spreadsheet_cell_start_nop#1\stopcell
+ {\bTD\getspr{#1}\eTD}
+
+\let\module_spreadsheet_cell_stop\relax
+
\protect
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{m-spreadsheet.mkiv}
\starttext
@@ -220,10 +167,12 @@ end
\bTD[nx=2] \bf \getspr{string.format("\letterpercent0.3f",(A[3] + B[3]) /100)} \eTD
\eTR
\bTR
- \bTD[nx=2] \bf \getspr{fmt("0.3f",(sum(A,1,2)) / 10)} \eTD
+ \bTD[nx=2] \bf \getspr{fmt("@0.3f",(sum(A,1,2)) / 10)} \eTD
\eTR
\eTABLE
+\setupspreadsheet[mysheet]
+
\startspreadsheet[mysheet]
\bTABLE[align=middle]
@@ -231,7 +180,7 @@ end
\bTD \getspr{100} \eTD \bTD test \setspr{30} \eTD
\eTR
\bTR
- \bTD \getspr{20} \eTD \bTD \getspr{4+3} \eTD
+ \bTD \getspr{20} \eTD \bTD \getspr{4+3.5} \eTD
\eTR
\bTR
\bTD \getspr{A[1] + A[2]} \eTD
@@ -244,17 +193,19 @@ end
\stopspreadsheet
-\startspreadsheettable
+\blank
+
+\setupspreadsheet[test][period={{\bf\middlered .}},comma={{\bf\middlegreen ,}},split=yes]
+
+\startspreadsheettable[test]
\startrow
- \startcell 3 \stopcell
- \startcell 9 \stopcell
+ \startcell 123456.78 \stopcell
+ \startcell 1234567.89 \stopcell
\startcell A[1] + B[1] \stopcell
\stoprow
\stopspreadsheettable
-bla bla \getspreadsheet[mysheet]{2}{2}{}
-
-bla bla \getspreadsheet[mysheet]{4}{1}{}
+\blank
% \showspreadsheet
% \showspreadsheet[mysheet]
diff --git a/tex/context/base/m-timing.mkiv b/tex/context/base/m-timing.mkiv
index e5413ddb1..62d2ad91b 100644
--- a/tex/context/base/m-timing.mkiv
+++ b/tex/context/base/m-timing.mkiv
@@ -54,7 +54,7 @@ end
\ctxlua{luatex.registerstopactions(function() moduledata.progress.save() end)}
\stopnotmode
-\def\ShowNamedUsage#1#2#3%
+\unexpanded\def\ShowNamedUsage#1#2#3%
{\setbox\scratchbox\vbox\bgroup\startMPcode
begingroup ; save p, q, b, h, w ;
path p, q, b ; numeric h, w ;
@@ -92,9 +92,9 @@ end
\stoplinecorrection
\fi}
-\def\LoadUsage #1{\ctxlua{moduledata.progress.convert("#1")}}
-\def\ShowUsage #1{\ctxlua{moduledata.progress.show("#1",nil,nil,"elapsed_time")}}
-\def\ShowMemoryUsage#1{\ctxlua{moduledata.progress.show("#1",nil,{}, "elapsed_time")}}
-\def\ShowNodeUsage #1{\ctxlua{moduledata.progress.show("#1",{},nil, "elapsed_time")}}
+\unexpanded\def\LoadUsage #1{\ctxlua{moduledata.progress.convert("#1")}}
+\unexpanded\def\ShowUsage #1{\ctxlua{moduledata.progress.show("#1",nil,nil,"elapsed_time")}}
+\unexpanded\def\ShowMemoryUsage#1{\ctxlua{moduledata.progress.show("#1",nil,{}, "elapsed_time")}}
+\unexpanded\def\ShowNodeUsage #1{\ctxlua{moduledata.progress.show("#1",{},nil, "elapsed_time")}}
\endinput
diff --git a/tex/context/base/m-translate.mkiv b/tex/context/base/m-translate.mkiv
index ae4f3899d..363f115cb 100644
--- a/tex/context/base/m-translate.mkiv
+++ b/tex/context/base/m-translate.mkiv
@@ -65,31 +65,40 @@
\unprotect
-\def\translateinput{\dodoubleargument\dotranslateinput}
+\unexpanded\def\translateinput
+ {\dodoubleargument\module_translate_input}
-\def\dotranslateinput[#1][#2]{\ctxlua{moduledata.translators.register(\!!bs#1\!!es,\!!bs#2\!!es)}}
+\def\module_translate_input[#1][#2]%
+ {\ctxlua{moduledata.translators.register(\!!bs#1\!!es,\!!bs#2\!!es)}}
-\def\resetinputtranslation {\ctxlua{moduledata.translators.reset()}}
-\def\enableinputtranslation {\ctxlua{moduledata.translators.enable()}}
-\def\disableinputtranslation{\ctxlua{moduledata.translators.disable()}}
+\unexpanded\def\resetinputtranslation
+ {\ctxlua{moduledata.translators.reset()}}
-\def\readtranslatedfile#1%
+\unexpanded\def\enableinputtranslation
+ {\ctxlua{moduledata.translators.enable()}}
+
+\unexpanded\def\disableinputtranslation
+ {\ctxlua{moduledata.translators.disable()}}
+
+\unexpanded\def\readtranslatedfile#1%
{\enableinputtranslation
\readfile{#1}\donothing\donothing
\disableinputtranslation}
\protect
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{m-translate.mkiv}
+
\starttext
\translateinput[Moica][Mojca]
- \translateinput[Idris][Idris (aka ادريس)]
+ % \translateinput[Idris][Idris (aka ادريس)]
+ \translateinput[Idris][Idris (aka <something arabic here>)]
\enableinputtranslation
- Well, it's not that hard to satisfy Idris and Moica.
+ Well, it's not that hard to satisfy Idris' and Moicas \TEX\ needs.
\readtranslatedfile{tufte}
diff --git a/tex/context/base/m-visual.mkiv b/tex/context/base/m-visual.mkiv
index 5d259f6ab..504c0d0c5 100644
--- a/tex/context/base/m-visual.mkiv
+++ b/tex/context/base/m-visual.mkiv
@@ -13,6 +13,9 @@
\unprotect
+%D Much will probably be replaced by \LUA\ based solutions which is
+%D rather trivial and fun doing.
+
%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.
@@ -28,11 +31,11 @@
\begingroup
\directcolored[fakerulecolor]%
\iffakebaseline
- \vrule\!!height1.25ex\!!depth-.05ex\!!width#1%
+ \vrule\s!height1.25ex\s!depth-.05ex\s!width#1%
\kern-#1%
- \vrule\!!height-.05ex\!!depth .25ex\!!width#1%
+ \vrule\s!height-.05ex\s!depth .25ex\s!width#1%
\else
- \vrule\!!height1.25ex\!!depth .25ex\!!width#1%
+ \vrule\s!height1.25ex\s!depth .25ex\s!width#1%
\fi
\endgroup
\allowbreak}
@@ -116,9 +119,9 @@
\ifx\dofakedroppedcaps\relax
{\fakeparindentcolor
\vrule
- \!!height \strutheight % not longer .5ex
- \!!depth \strutdepth % not longer 0pt
- \!!width \parindent}%
+ \s!height \strutheight % not longer .5ex
+ \s!depth \strutdepth % not longer 0pt
+ \s!width \parindent}%
\else
\dofakedroppedcaps \let\dofakedroppedcaps\relax
\fi
@@ -137,9 +140,9 @@
\advance\scratchdimen -\lineheight
\advance\scratchdimen \dp\strutbox
\vrule
- \!!width#1\wd\scratchbox
- \!!height\ht\scratchbox
- \!!depth\scratchdimen}%
+ \s!width#1\wd\scratchbox
+ \s!height\ht\scratchbox
+ \s!depth\scratchdimen}%
\ht\scratchbox\ht\strutbox
\dp\scratchbox\dp\strutbox
\hangindent\wd\scratchbox
@@ -214,7 +217,7 @@
{\hss\lower.5\ht\scratchbox\box\scratchbox\hss}%
\hbox to \zeropoint
{\hss
- \black\vrule\!!width6\linewidth\!!height3\linewidth\!!depth3\linewidth
+ \black\vrule\s!width6\linewidth\s!height3\linewidth\s!depth3\linewidth
\hss}}}
\unexpanded\def\bodyfontgrid
@@ -243,10 +246,564 @@
\placefigure{\fakewords{8}{15}}{\fakeimage{5cm}{3cm}{10cm}{5cm}}
\dorecurse{2}{\fakewords{100}{200}\endgraf}}}}}
+%D Moved code:
+
+%D \module
+%D [ file=trac-vis, % was core-vis,
+%D version=1996.06.01,
+%D title=\CONTEXT\ Tracking Macros,
+%D subtitle=Visualization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This module adds some more visualization cues to the ones
+%D supplied in the support module.
+%D
+%D %\everypar dual character, \the\everypar and \everypar=
+%D %\hrule cannot be grabbed in advance, switches mode
+%D %\vrule cannot be grabbed in advance, switches mode
+%D %
+%D %\indent only explicit ones
+%D %\noindent only explicit ones
+%D %\par only explicit ones
+%D
+%D %\leftskip only if explicit one
+%D %\rightskip only if explicit one
+
+\writestatus{loading}{ConTeXt Tracking Macros / Visualization}
+
+\unprotect
+
+%D \macros
+%D {indent, noindent, par}
+%D
+%D \TeX\ acts upon paragraphs. In mosts documents paragraphs
+%D are separated by empty lines, which internally are handled as
+%D \type{\par}. Paragraphs can be indented or not, depending on
+%D the setting of \type{\parindent}, the first token of a
+%D paragraph and/or user suppressed or forced indentation.
+%D
+%D Because the actual typesetting is based on both explicit
+%D user and implicit system actions, visualization is only
+%D possible for the user supplied \type{\indent},
+%D \type{\noindent}, and \type{\par}. Other
+%D 'clever' tricks will quite certainly lead to more failures
+%D than successes, so we only support these three explicit
+%D primitives and one macro:
+
+\unexpanded\def\showparagraphcue#1#2#3#4#5%
+ {\bgroup
+ \scratchdimen#1\relax
+ \dontinterfere
+ \dontcomplain
+ %boxrulewidth5\testrulewidth
+ #3#4\relax
+ \setbox\scratchbox\normalhbox to \scratchdimen
+ {#2{\ruledhbox to \scratchdimen
+ {\vrule #5 20\testrulewidth \s!width \zeropoint
+ \normalhss}}}%
+ \smashbox\scratchbox
+ \normalpenalty\plustenthousand
+ \box\scratchbox
+ \egroup}
+
+\unexpanded\def\ruledhanging
+ {\ifdim\hangindent>\zeropoint
+ \ifnum\hangafter<\zerocount
+ \normalhbox
+ {%boxrulewidth5\testrulewidth
+ \setbox\scratchbox\ruledhbox to \hangindent
+ {\scratchdimen\strutht
+ \advance\scratchdimen \strutdp
+ \vrule
+ \s!width \zeropoint
+ \s!height \zeropoint
+ \s!depth -\hangafter\scratchdimen}%
+ \normalhskip-\hangindent
+ \smashbox\scratchbox
+ \raise\strutht\box\scratchbox}%
+ \fi
+ \fi}
+
+\unexpanded\def\ruledparagraphcues
+ {\bgroup
+ \dontcomplain
+ \normalhbox to \zeropoint
+ {\ifdim\leftskip>\zeropoint\relax
+ \showparagraphcue\leftskip\llap\relax\relax\!!depth
+ \normalhskip-\leftskip
+ \fi
+ \ruledhanging
+ \normalhskip\hsize
+ \ifdim\rightskip>\zeropoint\relax
+ \normalhskip-\rightskip
+ \showparagraphcue\rightskip\relax\relax\relax\!!depth
+ \fi}%
+ \egroup}
+
+\unexpanded\def\ruledpar
+ {\relax
+ \ifhmode
+ \showparagraphcue{40\testrulewidth}\relax\rightrulefalse\relax\s!height
+ \fi
+ \normalpar}
+
+\unexpanded\def\rulednoindent
+ {\relax
+ \normalnoindent
+ \ruledparagraphcues
+ \showparagraphcue{40\testrulewidth}\llap\leftrulefalse\relax\s!height}
+
+\unexpanded\def\ruledindent
+ {\relax
+ \normalnoindent
+ \ruledparagraphcues
+ \ifdim\parindent>\zeropoint
+ \showparagraphcue\parindent\relax\relax\relax\s!height
+ \else
+ \showparagraphcue{40\testrulewidth}\llap\relax\relax\s!height
+ \fi
+ \normalhskip\parindent}
+
+\unexpanded\def\dontshowimplicits
+ {\let\noindent \normalnoindent
+ \let\indent \normalindent
+ \let\par \normalpar}
+
+\unexpanded\def\showimplicits
+ {\testrulewidth \defaulttestrulewidth
+ \let\noindent \rulednoindent
+ \let\indent \ruledindent
+ \let\par \ruledpar}
+
+%D The next few||line examples show the four cues. Keep in
+%D mind that we only see them when we explicitly open or close
+%D a paragraph.
+%D
+%D \bgroup
+%D \def\voorbeeld#1%
+%D {#1Visualizing some \TeX\ primitives and Plain \TeX\
+%D macros can be very instructive, at least it is to me.
+%D Here we see {\tt\string#1} and {\tt\string\ruledpar} in
+%D action, while {\tt\string\parindent} equals
+%D {\tt\the\parindent}.\ruledpar}
+%D
+%D \showimplicits
+%D
+%D \voorbeeld \indent
+%D \voorbeeld \noindent
+%D
+%D \parindent=60pt
+%D
+%D \voorbeeld \indent
+%D \voorbeeld \noindent
+%D
+%D \startnarrower
+%D \voorbeeld \indent
+%D \voorbeeld \noindent
+%D \stopnarrower
+%D \egroup
+%D
+%D These examples also demonstrate the visualization of
+%D \type {\leftskip} and \type {\rightskip}. The macro
+%D \type {\nofruledbaselines} determines the number of lines
+%D shown.
+
+\newcounter\ruledbaselines
+
+\def\nofruledbaselines{3}
+
+\unexpanded\def\ruledbaseline
+ {\vrule \s!width \zeropoint
+ \bgroup
+ \dontinterfere
+ \doglobal\increment\ruledbaselines
+ \scratchdimen\nofruledbaselines\baselineskip
+ \setbox\scratchbox\normalvbox to 2\scratchdimen
+ {\leaders
+ \normalhbox
+ {\strut
+ \vrule
+ \s!height \testrulewidth
+ \s!depth \testrulewidth
+ \s!width 120\points}
+ \normalvfill}%
+ \smashbox\scratchbox
+ \advance\scratchdimen \strutheightfactor\baselineskip
+ \setbox\scratchbox\normalhbox
+ {\normalhskip -48\points
+ \normalhbox to 24\points
+ {\normalhss
+ {\ttxx\ruledbaselines}%
+ \normalhskip6\points}%
+ \raise\scratchdimen\box\scratchbox}%
+ \smashbox\scratchbox
+ \box\scratchbox
+ \egroup}
+
+\unexpanded\def\showbaselines
+ {\testrulewidth\defaulttestrulewidth
+ \EveryPar{\ruledbaseline}}
+
+%D \macros
+%D {showpagebuilder}
+%D
+%D The next tracing option probaly is only of use to me and a
+%D few \CONTEXT\ hackers.
+
+\unexpanded\def\showpagebuilder
+ {\EveryPar{\doshowpagebuilder}}
+
+\unexpanded\def\doshowpagebuilder
+ {\strut\llap
+ {\startcolor[blue]\vl
+ \high{\infofont v:\the\vsize }\vl
+ \high{\infofont g:\the\pagegoal }\vl
+ \high{\infofont t:\the\pagetotal}\vl
+ \stopcolor}}
+
+%D \macros
+%D {colormarkbox,rastermarkbox}
+%D
+%D This macro is used in the pagebody routine. No other use
+%D is advocated here.
+%D
+%D \starttyping
+%D \colormarkbox0
+%D \stoptyping
+
+\def\colormarkoffset{\cutmarkoffset}
+\def\colormarklength{\cutmarklength}
+
+\def\dodocolorrangeA#1%
+ {\fastcolored[#1]{\hrule\s!width3em\s!height\scratchdimen\s!depth\zeropoint}}
+
+\def\docolorrangeA#1 #2 %
+ {\vbox
+ {\hsize3em % \scratchdimen
+ \ifcase#1\or
+ \dodocolorrangeA{c=#2}\or
+ \dodocolorrangeA{m=#2}\or
+ \dodocolorrangeA{y=#2}\or
+ \dodocolorrangeA{m=#2,y=#2}\or
+ \dodocolorrangeA{c=#2,y=#2}\or
+ \dodocolorrangeA{c=#2,m=#2}\fi
+ \ifdim\scratchdimen>1ex
+ \vskip-\scratchdimen
+ \vbox to \scratchdimen
+ {\vss\hbox to 3em{\hss#2\hss}\vss}%
+ \fi}}
+
+\def\colorrangeA#1%
+ {\vbox
+ {\startcolor[\s!white]%
+ \scratchdimen\dimexpr(-\colormarklength*4+\tractempheight+\tractempdepth)/21\relax
+ \offinterlineskip
+ \docolorrangeA #1 1.00 \docolorrangeA #1 0.95
+ \docolorrangeA #1 0.75
+ \docolorrangeA #1 0.50
+ \docolorrangeA #1 0.25 \docolorrangeA #1 0.05
+ \docolorrangeA #1 0.00
+ \stopcolor}}
+
+\def\docolorrangeB #1 #2 #3 #4 #5 %
+ {\fastcolored
+ [\c!c=#2,\c!m=#3,\c!y=#4,\c!k=#5]
+ {\vrule\s!width\scratchdimen\s!height\colormarklength\s!depth\zeropoint}%
+ \ifdim\scratchdimen>2em
+ \hskip-\scratchdimen
+ \vbox to \colormarklength
+ {\vss\hbox to \scratchdimen{\hss#1\hss}\vss}%
+ \fi}
+
+\def\colorrangeB
+ {\hbox
+ {\startcolor[\s!white]%
+ \scratchdimen\dimexpr(-\colormarklength*\plustwo+\tractempwidth)/11\relax
+ \docolorrangeB .5~C .5 0 0 0
+ \docolorrangeB .5~M 0 .5 0 0
+ \docolorrangeB .5~Y 0 0 .5 0
+ \docolorrangeB .5~K 0 0 0 .5
+ \docolorrangeB C 1 0 0 0
+ \docolorrangeB G 1 0 1 0
+ \docolorrangeB Y 0 0 1 0
+ \docolorrangeB R 0 1 1 0
+ \docolorrangeB M 0 1 0 0
+ \docolorrangeB B 1 1 0 0
+ \docolorrangeB K 0 0 0 1
+ \stopcolor}}
+
+\def\docolorrangeC#1 %
+ {\fastcolored
+ [\c!s=#1]%
+ {\vrule\s!width\scratchdimen\s!height\colormarklength\s!depth\zeropoint}%
+ \ifdim\scratchdimen>2em
+ \hskip-\scratchdimen
+ \vbox to \colormarklength
+ {\vss\hbox to \scratchdimen{\hss#1\hss}\vss}%
+ \fi}
+
+\def\colorrangeC
+ {\hbox
+ {\startcolor[\s!white]%
+ \scratchdimen\dimexpr(-\colormarklength*2+\tractempwidth)/14\relax
+ \docolorrangeC 1 \docolorrangeC .95
+ \docolorrangeC .9 \docolorrangeC .85
+ \docolorrangeC .8 \docolorrangeC .75
+ \docolorrangeC .7
+ \docolorrangeC .6
+ \docolorrangeC .5
+ \docolorrangeC .4
+ \docolorrangeC .3
+ \docolorrangeC .2
+ \docolorrangeC .1
+ \docolorrangeC 0
+ \stopcolor}}
+
+\def\docolormarkbox#1#2%
+ {\tractempheight\ht#2%
+ \tractempdepth \dp#2%
+ \tractempwidth \wd#2%
+ \setbox#2\hbox
+ {\scratchdimen\dimexpr\colormarklength/2\relax
+ \forgetall
+ \ssxx
+ \setbox\scratchbox\vbox
+ {\offinterlineskip
+ \vskip\dimexpr-\colormarkoffset\scratchdimen-2\scratchdimen\relax
+ \ifcase#1\relax
+ \vskip\dimexpr\colormarklength+\scratchdimen+\tractempheight\relax
+ \else
+ \hbox to \tractempwidth{\hss\hbox{\colorrangeB}\hss}%
+ \vskip\colormarkoffset\scratchdimen
+ \vbox to \tractempheight
+ {\vss
+ \hbox to \tractempwidth
+ {\llap{\colorrangeA1\hskip\colormarkoffset\scratchdimen}\hfill
+ \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA4}}%
+ \vss
+ \hbox to \tractempwidth
+ {\llap{\colorrangeA2\hskip\colormarkoffset\scratchdimen}\hfill
+ \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA5}}%
+ \vss
+ \hbox to \tractempwidth
+ {\llap{\colorrangeA3\hskip\colormarkoffset\scratchdimen}\hfill
+ \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA6}}%
+ \vss}%
+ \fi
+ \vskip\colormarkoffset\scratchdimen
+ \hbox to \tractempwidth
+ {\hss\lower\tractempdepth\hbox{\colorrangeC}\hss}}%
+ \ht\scratchbox\tractempheight
+ \dp\scratchbox\tractempdepth
+ \wd\scratchbox\zeropoint
+ \box\scratchbox
+ \box#2}%
+ \wd#2\tractempwidth
+ \ht#2\tractempheight
+ \dp#2\tractempdepth}
+
+\unexpanded\def\colormarkbox {\docolormarkbox\plusone } % #1
+\unexpanded\def\rastermarkbox{\docolormarkbox\zerocount} % #1
+
+%D \macros
+%D {showwhatsits, dontshowwhatsits}
+%D
+%D \TEX\ has three so called whatsits: \type {\mark}, \type
+%D {\write} and \type {\special}. The first one keeps track of
+%D the current state at page boundaries, the last two are used
+%D to communicate to the outside world. Due to fact that
+%D especially \type {\write} is often used in conjunction with
+%D \type {\edef}, we can only savely support that one in \ETEX.
+%D
+%D \bgroup \showwhatsits \setupcolors[state=start]
+%D
+%D Whatsits show up \color[blue]{in color} and are
+%D characterized bij their first character.\footnote [some note]
+%D {So we may encounter \type {w}, \type {m} and \type{s}.}
+%D They are \writestatus{dummy}{demo}\color[yellow]{stacked}.
+%D
+%D \egroup
+
+\newif\ifimmediatewrite
+
+\let\supernormalmark \normalmark % mark may already been superseded
+\let\supernormalmarks \normalmarks % mark may already been superseded
+
+\unexpanded\def\showwhatsits
+ {\protected\def\normalmark {\visualwhatsit100+m\supernormalmark }%
+ \protected\def\normalmarks{\visualwhatsit100+m\supernormalmarks}%
+ \protected\def\special {\visualwhatsit0100s\normalspecial }%
+ \protected\def\write {\visualwhatsit001-w\normalwrite }%
+ \let\immediate\immediatewhatsit
+ \appendtoks\dontshowwhatsits\to\everystoptext}
+
+\unexpanded\def\immediatewhatsit
+ {\bgroup\futurelet\next\doimmediatewhatsit}
+
+\unexpanded\def\doimmediatewhatsit
+ {\ifx\next\write
+ \egroup\immediatewritetrue
+ \else
+ \egroup\expandafter\normalimmediate
+ \fi}
+
+\unexpanded\def\dontshowwhatsits
+ {\let\immediate \normalimmediate
+ \let\normalmark\supernormalmark
+ \let\special \normalspecial
+ \let\write \normalwrite}
+
+\unexpanded\def\visualwhatsit#1#2#3#4#5%
+ {\bgroup
+ \pushwhatsit
+ \dontinterfere
+ \dontcomplain
+ \dontshowcomposition
+ \dontshowwhatsits
+ \ttx
+ \ifvmode\donetrue\else\donefalse\fi
+ \setbox\scratchbox\hbox
+ {\ifdone
+ \colored[r=#1,g=#2,b=#3]{#5}% temp hack
+ \else
+ \colored[s=0]{#5}% temp hack
+ \fi}%
+ \setbox\scratchbox\hbox
+ {\ifdone
+ \colored[r=#1,g=#2,b=#3]{\vrule\s!width\wd\scratchbox}% temp hack
+ \else
+ \colored[s=0]{\vrule\s!width\wd\scratchbox}% temp hack
+ \fi
+ \hskip-\wd\scratchbox\box\scratchbox}%
+ \scratchdimen1ex
+ \setbox\scratchbox\hbox
+ {\ifdone\hskip\else\raise#4\fi\scratchdimen\box\scratchbox}%
+ \smashbox\scratchbox
+ \ifdone\nointerlineskip\fi
+ \box\scratchbox
+ \ifvmode\nointerlineskip\fi
+ \popwhatsit
+ \egroup
+ \ifimmediatewrite
+ \immediatewritefalse
+ \expandafter\normalimmediate
+ \fi}
+
+\unexpanded\def\pushwhatsit
+ {\ifzeropt\lastskip
+ \ifcase\lastpenalty
+ \ifzeropt\lastkern
+ \ifhmode
+ \let\popwhatsit\relax
+ \else
+ \edef\popwhatsit{\prevdepth\the\prevdepth}%
+ \fi
+ \else
+ \ifhmode
+ \edef\popwhatsit{\kern\the\lastkern}\unkern
+ \else
+ \edef\popwhatsit{\kern\the\lastkern\prevdepth\the\prevdepth}%
+ \kern-\lastkern
+ \fi
+ \fi
+ \else
+ \ifhmode
+ \edef\popwhatsit{\the\lastpenalty}%
+ \unpenalty
+ \else
+ \edef\popwhatsit{\penalty\the\lastpenalty\prevdepth\the\prevdepth}%
+ %\nobreak
+ \fi
+ \fi
+ \else
+ \ifhmode
+ \edef\popwhatsit{\hskip\the\lastskip}\unskip
+ \else
+ \edef\popwhatsit{\vskip\the\lastskip\prevdepth\the\prevdepth}%
+ \vskip-\lastskip
+ \fi
+ \fi}
+
+%D The next macro can be used to keep track of classes of
+%D boxes (handy for development cq.\ tracing).
+
+\def\dodotagbox#1#2#3% can be reimplemented
+ {\def\next##1##2##3##4%
+ {\vbox to \ht#2{##3\hbox to \wd#2{##1#3##2}##4}}%
+ \processaction
+ [#1]
+ [ l=>\next\relax\hfill\vfill\vfill,
+ r=>\next\hfill\relax\vfill\vfill,
+ t=>\next\hfill\hfill\relax\vfill,
+ b=>\next\hfill\hfill\vfill\relax,
+ lt=>\next\relax\hfill\relax\vfill,
+ lb=>\next\relax\hfill\vfill\relax,
+ rt=>\next\hfill\relax\relax\vfill,
+ rb=>\next\hfill\relax\vfill\relax,
+ tl=>\next\relax\hfill\relax\vfill,
+ bl=>\next\relax\hfill\vfill\relax,
+ tr=>\next\hfill\relax\relax\vfill,
+ br=>\next\hfill\relax\vfill\relax,
+ \s!default=>\next\hfill\hfill\vfill\vfill,
+ \s!unknown=>\next\hfill\hfill\vfill\vfill]}
+
+\def\dotagbox[#1]#2%
+ {\bgroup
+ \dowithnextbox
+ {\setbox\scratchbox\flushnextbox
+ \setbox\nextbox\ifhbox\nextbox\hbox\else\vbox\fi
+ \bgroup
+ \startoverlay
+ {\copy\scratchbox}
+ {\dodotagbox{#1}\scratchbox{\framed
+ [\c!background=\v!screen,\c!backgroundscreen=1]{#2}}}
+ \stopoverlay
+ \egroup
+ \nextboxwd\the\wd\scratchbox
+ \nextboxht\the\ht\scratchbox
+ \nextboxdp\the\dp\scratchbox
+ \flushnextbox
+ \egroup}}
+
+\unexpanded\def\tagbox
+ {\dosingleempty\dotagbox}
+
+%D \macros
+%D {coloredhbox,coloredvbox,coloredvtop,
+%D coloredstrut}
+%D
+%D The following visualizations are used in some of the manuals:
+
+\definecolor[boxcolor:ht][r=.5,g=.75,b=.5]
+\definecolor[boxcolor:dp][r=.5,g=.5,b=.75]
+\definecolor[boxcolor:wd][r=.75,g=.5,b=.5]
+\definecolor[strutcolor] [r=.5,g=.25,b=.25]
+
+\unexpanded\def\coloredbox#1%
+ {\dowithnextbox{#1{\hbox
+ {\blackrule[\c!width=\nextboxwd,\c!height=\nextboxht,\c!depth=\zeropoint,\c!color=boxcolor:ht]%
+ \hskip-\nextboxwd
+ \blackrule[\c!width=\nextboxwd,\c!height=\zeropoint,\c!depth=\nextboxdp,\c!color=boxcolor:dp]%
+ \hskip-\nextboxwd
+ \box\nextbox}}}#1}
+
+\unexpanded\def\coloredhbox{\coloredbox\hbox}
+\unexpanded\def\coloredvbox{\coloredbox\vbox}
+\unexpanded\def\coloredvtop{\coloredbox\vtop}
+
+\unexpanded\def\coloredstrut
+ {\color[strutcolor]{\def\strutwidth{2\points}\setstrut\strut}}
+
+\protect
+
\continueifinputfile{m-visual.mkiv}
\starttext
\simplethesis
\stoptext
-
-\protect \endinput
diff --git a/tex/context/base/math-act.lua b/tex/context/base/math-act.lua
index 278d323c6..9894fa172 100644
--- a/tex/context/base/math-act.lua
+++ b/tex/context/base/math-act.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['math-act'] = {
license = "see context related readme files"
}
+-- Here we tweak some font properties (if needed).
+
local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end)
local report_math = logs.reporter("mathematics","initializing")
diff --git a/tex/context/base/math-ali.mkiv b/tex/context/base/math-ali.mkiv
index 94800b3ba..9e6fda074 100644
--- a/tex/context/base/math-ali.mkiv
+++ b/tex/context/base/math-ali.mkiv
@@ -15,17 +15,6 @@
\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. In the
%D meantime this code has been adapted to \MKIV\ but mnore is possible.
@@ -38,19 +27,25 @@
% n>1 #### needed, strange # interaction in recurse
+\newtoks\c_math_align_a
+\newtoks\c_math_align_b
+\newtoks\c_math_align_c
+
\def\math_build_eqalign
{\scratchtoks\emptytoks
- \dorecurse{\mathalignmentparameter\c!m}
- {\ifnum\recurselevel>\plusone
- %\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}}}
+ \dorecurse{\mathalignmentparameter\c!m}\math_build_eqalign_step
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_c}}}
+
+\def\math_build_eqalign_step
+ {\ifnum\recurselevel>\plusone
+ %\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\c_math_align_a}}%
+ \dorecurse{\numexpr\mathalignmentparameter\c!n-\plusone\relax}
+ {\normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_b}}}}
\def\math_math_in_eqalign#1{$\tabskip\zeropoint\everycr\emptytoks\displaystyle{{}#1{}}$}
\def\math_text_in_eqalign#1{$\tabskip\zeropoint\everycr\emptytoks#1$}
@@ -73,14 +68,14 @@
% 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}%
+ {\c_math_align_a{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}%
+ \c_math_align_b{&\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\math_text_in_eqalign{##}\tabskip\zeropoint}%
+ \c_math_align_c{\hfil&\span\math_text_in_eqalign{##}\tabskip\zeropoint}%
\else\ifnum\mathraggedstatus=\plusthree
- \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\span\math_text_in_eqalign{##}\tabskip\zeropoint}%
+ \c_math_align_c{\hfil\tabskip\zeropoint\s!plus 1\s!fill&\span\math_text_in_eqalign{##}\tabskip\zeropoint}%
\else
- \!!toksc{\hfil\tabskip\centering&\llap{\span\math_text_in_eqalign{##}}\tabskip\zeropoint}%
+ \c_math_align_c{\hfil\tabskip\centering&\llap{\span\math_text_in_eqalign{##}}\tabskip\zeropoint}%
\fi\fi
\global\mathnumberstatus\zerocount
\math_build_eqalign
@@ -88,31 +83,31 @@
\tabskip\centering}
\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}%
+ {\c_math_align_a{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}%
+ \c_math_align_b{&\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\math_text_in_eqalign{##}}\tabskip\displaywidth}%
+ \c_math_align_c{\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\math_rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}%
+ \c_math_align_c{\hfil\tabskip\zeropoint\s!plus 1\s!fill&\kern-\displaywidth\span\math_rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}%
\else
- \!!toksc{\hfil\tabskip\centering&\kern-\displaywidth\rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}%
+ \c_math_align_c{\hfil\tabskip\centering&\kern-\displaywidth\rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}%
\fi\fi
\global\mathnumberstatus\zerocount
\math_build_eqalign
\the\mathdisplayaligntweaks
\tabskip\centering}
-\def\math_both_eqalign_no#1#2%
+\def\math_both_eqalign_no_normal#1#2%
{\ifmmode
- \the\mathdisplayaligntweaks % \let\doplaceformulanumber\relax % strange hack
+ \the\mathdisplayaligntweaks % \let\strc_formulas_place_number\relax % strange hack
\vcenter\bgroup
\let\math_finish_eqalign_no\egroup
\else
\let\math_finish_eqalign_no\relax
\fi
#1%
- \halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA {\the\scratchtoks\crcr#2\crcr}%
+ \halign \ifcase\eqalignmode \or to \displaywidth \fi \expandafter {\the\scratchtoks\crcr#2\crcr}%
\math_finish_eqalign_no}
\def\math_both_eqalign_no_aligned#1%
@@ -128,7 +123,7 @@
\fi
\fi
#1%
- \halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA \bgroup\the\scratchtoks\crcr}
+ \halign \ifcase\eqalignmode \or to \displaywidth \fi \expandafter \bgroup\the\scratchtoks\crcr}
\def\math_rlap#1%
{\setbox\scratchbox\hbox{#1}%
@@ -158,7 +153,7 @@
\newtoks \everymathalignment
\def\math_alignment_NR_indeed[#1][#2]%
- {\donestedformulanumber{#1}{#2}% to be tagged (better an attribute)
+ {\strc_formulas_place_number_nested{#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
@@ -221,7 +216,7 @@
\setupmathalignment
[\c!n=2,
\c!m=1,
- \c!distance=1em]
+ \c!distance=\emwidth]
\definemathalignment[align] % default case (this is what amstex users expect)
\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing)
@@ -265,7 +260,7 @@
\letvalue{\??mathalignmentvariant\v!middle}\plusthree
\def\math_align_NR_generic[#1][#2]%
- {\donestedformulanumber{#1}{#2}\crcr}
+ {\strc_formulas_place_number_nested{#1}{#2}\crcr}
%D \starttyping
%D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0]
@@ -408,8 +403,8 @@
\installcommandhandler \??mathcases {mathcases} \??mathcases
\setupmathcases
- [\c!distance=1em,
- \c!numberdistance=2.5em,
+ [\c!distance=\emwidth,
+ \c!numberdistance=2.5\emwidth,
\c!left={\left\{\mskip\thinmuskip},
\c!right={\right.}]
@@ -434,7 +429,7 @@
\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}%
+ \def\NR{\unskip\endmath&\global\let\math_cases_NC\math_cases_NC_indeed\dodirectdoubleempty\math_cases_NR}%
\normalbaselines
\mathsurround\zeropoint
\everycr\emptytoks
@@ -515,7 +510,7 @@
\installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix
\setupmathmatrix
- [\c!distance=1em,
+ [\c!distance=\emwidth,
\c!left=,
\c!right=,
\c!align=\v!middle]
@@ -570,20 +565,20 @@
\definemathmatrix[\v!mathmatrix]
\def\math_matrix_prepare
- {\!!toksa{\strut\math_first_in_eqalign\math_left_of_equalign\span
+ {\c_math_align_a{\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
+ \c_math_align_b{&\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
+ \c_math_align_c{&&\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}}%
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_a}}%
\dorecurse{\numexpr\scratchcounter-\plusone\relax}
- {\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksb}}}%
- \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksc}}%
- \halign \@EA \bgroup\the\scratchtoks \crcr}
+ {\normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_b}}}%
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\c_math_align_c}}%
+ \halign \expandafter \bgroup\the\scratchtoks \crcr}
\unexpanded\def\dodomatrixNC
{\gdef\domatrixNC{\endmath&}}
@@ -887,10 +882,10 @@
\expandafter\mathbin
\else\ifdim\wd\scratchbox>\zeropoint
\endgroup
- \expandafter\expandafter\expandafter\mathrel
+ \doubleexpandafter\mathrel
\else
\endgroup
- \expandafter\expandafter\expandafter\firstofoneargument
+ \doubleexpandafter\firstofoneargument
\fi\fi}
\unexpanded\def\overset#1#2%
@@ -947,7 +942,7 @@
\let\normalleqno\leqno
\let\normaleqno \eqno
% added
- \doplaceformulanumber
+ \strc_formulas_place_number
\setbox\scratchbox\math_hbox to \displaywidth\bgroup
\mathinnerstrut
$%
diff --git a/tex/context/base/math-arr.mkiv b/tex/context/base/math-arr.mkiv
index f18d6be2b..5b50303d0 100644
--- a/tex/context/base/math-arr.mkiv
+++ b/tex/context/base/math-arr.mkiv
@@ -30,156 +30,112 @@
% \mathord\rightarrow
% $}
%
-% \def\leftarrowfill % brrr no longer in luated
+% \def\leftarrowfill % brrr no longer in luatex
% {$%
% \mathsurround\zeropoint
% \mathord\leftarrow
% \mkern-7mu%
% \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
% \mkern-7mu
-% \smash-$
+% \smash-%
% $}
-\def\exmthfont#1{\mr} % \symbolicsizedfont#1\plusone{MathExtension}}
-
-\def\domthfrac#1#2#3#4#5#6#7%
+\def\math_stylebuilders_fract#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
+ \dimen0\wd\ifdim\wd2>\wd0 2\else 0\fi
\setbox4\hbox to \dimen0{\leaders\hbox{#4}\hss#5}%
\mathord{\vcenter{{\offinterlineskip
\hbox to \dimen0{\hss\box0\hss}%
- \kern \ht4%
+ \kern\ht4%
\hbox to \dimen0{\hss\copy4\hss}%
- \kern \ht4%
+ \kern\ht4%
\hbox to \dimen0{\hss\box2\hss}}}}%
\endgroup}
-\def\domthsqrt#1#2#3#4#5%
+\def\math_stylebuilders_sqrt#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}}}%
+ \ht0\dimexpr1.05\ht0+\onepoint\relax
+ \dp0\dimexpr1.05\dp0+\onepoint\relax
+ \setbox4\hbox to \wd0{\mr#2\leaders\hbox{#3}\hfill#4}%
+ \delimitershortfall\zeropoint
+ \nulldelimiterspace\zeropoint
+ \setbox2\hbox{$\left\delimiter"0270370 \vrule \s!height\ht0 \s!depth \dp0 \s!width\zeropoint\right.$}% is this the right code point?
+ \mathord{\vcenter{\hbox{\copy2\rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}%
\endgroup}
\def\mthfrac#1#2#3#4#5{\mathchoice
- {\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}}}
+ {\math_stylebuilders_frac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}%
+ {\math_stylebuilders_frac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}%
+ {\math_stylebuilders_frac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}%
+ {\math_stylebuilders_frac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}}
\def\mthsqrt#1#2#3{\mathchoice
- {\domthsqrt\displaystyle \textface {#1}{#2}{#3}}%
- {\domthsqrt\textstyle \textface {#1}{#2}{#3}}%
- {\domthsqrt\scriptstyle \textface {#1}{#2}{#3}}%
- {\domthsqrt\scriptscriptstyle\textface {#1}{#2}{#3}}}
-
-% temp here
-
-%D We next define extensible arrows. Extensible arrows are arrows that
-%D change their length according to the width of the text to be placed
-%D above and below the arrow. Since we need to define a lot of arrows,
-%D we first define some helper macros. The basic idea is to measure
-%D the width of the box to be placed above and below the arrow, and
-%D make the \quotation{body} of the arrow as long as the bigger of the
-%D two widths.
-
-\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
+ {\math_stylebuilders_sqrt\displaystyle \textface{#1}{#2}{#3}}%
+ {\math_stylebuilders_sqrt\textstyle \textface{#1}{#2}{#3}}%
+ {\math_stylebuilders_sqrt\scriptstyle \textface{#1}{#2}{#3}}%
+ {\math_stylebuilders_sqrt\scriptscriptstyle\textface{#1}{#2}{#3}}}
+
+%D We next define extensible arrows. Extensible arrows are arrows that change their
+%D length according to the width of the text to be placed above and below the arrow.
+%D Since we need to define a lot of arrows, we first define some helper macros. The
+%D basic idea is to measure the width of the box to be placed above and below the
+%D arrow, and make the \quote {body} of the arrow as long as the bigger of the two
+%D widths.
+
+\installcorenamespace{matharrowsettings}
+
+\def\m_math_arrows_factor{1}
+\def\m_math_arrows_extra {0}
+
+\setvalue{\??matharrowsettings\v!none }{\def\m_math_arrows_factor{0}}
+\setvalue{\??matharrowsettings\v!small }{\def\m_math_arrows_extra{10}}
+\setvalue{\??matharrowsettings\v!medium }{\def\m_math_arrows_extra{15}}
+\setvalue{\??matharrowsettings\v!big }{\def\m_math_arrows_extra{20}}
+\setvalue{\??matharrowsettings\v!normal }{}
+\setvalue{\??matharrowsettings }{}
+\setvalue{\??matharrowsettings\s!unknown}{\doifnumberelse\p_math_spacing{\let\m_math_arrows_extra\p_math_spacing}\donothing}
+
+\def\math_arrows_construct#1#2#3#4#5% hm, looks like we do a double mathrel (a bit cleaned up .. needs checking)
{\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]%
+ \def\m_math_arrows_factor{1}%
+ \def\m_math_arrows_extra {0}%
+ \edef\p_math_spacing{#1}%
+ \csname\??matharrowsettings
+ \ifcsname\??matharrowsettings\p_math_spacing\endcsname\p_math_spacing\else\s!unknown\fi
+ \endcsname
\mathsurround\zeropoint
- \muskip0=\thirdoffourarguments #2mu
- \muskip2=\fourthoffourarguments #2mu
- \muskip0=\mtharrfactor\muskip0
- \muskip2=\mtharrfactor\muskip2
- \advance\muskip0 \mtharrextra mu
- \advance\muskip2 \mtharrextra mu
- \advance\muskip0 \firstoffourarguments #2mu
- \advance\muskip2 \secondoffourarguments #2mu
+ \muskip0=\muexpr\m_math_arrows_factor\muexpr\thirdoffourarguments #2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\firstoffourarguments #2\onemuskip\relax
+ \muskip2=\muexpr\m_math_arrows_factor\muexpr\fourthoffourarguments#2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\secondoffourarguments#2\onemuskip\relax
\setbox0\hbox{$\scriptstyle
\mkern\muskip0\relax
#5\relax
\mkern\muskip2\relax
$}%
- \setbox4\hbox{#3\displaystyle}%
- \dimen0\wd0
- \ifdim\wd4>\dimen0 \dimen0\wd4 \fi
\setbox2\hbox{$\scriptstyle
\mkern\muskip0\relax
#4\relax
\mkern\muskip2\relax
$}%
- \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
- \setbox4\hbox to \dimen0{#3\displaystyle}%
+ \setbox4\hbox{#3\displaystyle}%
+ \dimen0\wd0\relax
+ \ifdim\wd2>\dimen0
+ \dimen0\wd2\relax
+ \fi
+ \ifdim\wd4>\dimen0
+ \dimen0\wd4\relax
+ \fi
+ \ifdim\wd4=\dimen0\else
+ \setbox4\hbox to \dimen0{#3\displaystyle}%
+ \fi
\mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits\normalsuperscript{\box0}\normalsubscript{\box2}}%
\endgroup}
-\let\domthxarrsingle\domthxarr
+\let\math_arrows_construct_single\math_arrows_construct
%D There are some arrows which are created by stacking two arrows. The next
%D macro helps in defining such \quotation{double arrows}.
@@ -194,29 +150,27 @@
% \chemical{SO_2}
% \stopchemicalformula
-\def\domthxarrdouble#1#2#3#4#5#6#7% opt l r sp rs top bot
+\def\math_arrows_construct_double#1#2#3#4#5#6#7% opt l r sp rs top bot
{\mathrel
- {\scratchdimen.32ex\relax % was .22, todo: make configurable
- \setbox0\hbox{$\domthxarr{#1}{#2}{#4}{\phantom{#6}}{#7}$}%
- \setbox2\hbox{$\domthxarr{#1}{#3}{#5}{#6}{\phantom{#7}}$}%
+ {\scratchdimen.32\exheight\relax % was .22, todo: make configurable
+ \setbox0\hbox{$\math_arrows_construct{#1}{#2}{#4}{\phantom{#6}}{#7}$}%
+ \setbox2\hbox{$\math_arrows_construct{#1}{#3}{#5}{#6}{\phantom{#7}}$}%
\raise\scratchdimen\box0
\kern-\wd2
\lower\scratchdimen\box2}}
%D \macros{definematharrow}
%D
-%D Macro for defining new arrows. We can define two types of
-%D arrows|<|single arrows and double arrows. Single arrows are defined
-%D as
+%D Macro for defining new arrows. We can define two types of arrows|<|single arrows
+%D and double arrows. Single arrows are defined as
%D
%D \starttyping
%D \definematharrow [xrightarrow] [0359] [\rightarrowfill]
%D \stoptyping
%D
-%D The first argument is the name of the arrow (\tex{xrightarrow} in
-%D this case.) The second argument consists of a set of 4 numbers and
-%D specify the spacing correction in math units~\type{mu}. These
-%D numbers define:
+%D The first argument is the name of the arrow (\tex {xrightarrow} in this case.) The
+%D second argument consists of a set of 4 numbers and specify the spacing correction
+%D in math units~\type {mu}. These numbers define:
%D
%D \startlines
%D 1st number: arrow||tip correction
@@ -225,9 +179,9 @@
%D 4th number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
%D \stoplines
%D
-%D The third argument is the name of the extensible fill. The third
-%D argument is optional when the arrow is redefined later (this is
-%D useful for font specific tweaking of the skips.) For example,
+%D The third argument is the name of the extensible fill. The third argument is optional
+%D when the arrow is redefined later (this is useful for font specific tweaking of the
+%D skips.) For example,
%D
%D \startbuffer
%D \math{\xrightarrow{above}}
@@ -245,78 +199,80 @@
%D [\rightharpoonupfill,\leftharpoondownfill]
%D \stoptyping
%D
-%D The second and the third set of arguments consist of comma
-%D separated values. The first element of the second argument
-%D (\type{3095}) corresponds to the spacing correction of top arrow
-%D fill (\tex{rightarrowupfill}). Similarly, \type{0359} corresponds
-%D to bottom arrow fill \tex{leftharpoondownfill}). Stacking them on
-%D top of each other we get $\xrightleftharpoons[big]{above}{below}$.
-%D The following math arrows are defined
+%D The second and the third set of arguments consist of comma separated values. The
+%D first element of the second argument (\type {3095}) corresponds to the spacing
+%D correction of top arrow fill (\tex{rightarrowupfill}). Similarly, \type {0359}
+%D corresponds to bottom arrow fill \tex {leftharpoondownfill}). Stacking them on
+%D top of each other we get $\xrightleftharpoons [big] {above} {below}$. The
+%D following math arrows are defined
%D
%D \placetable[none]{}{\starttable[|l|m|]
-%D \NC \tex{xrightarrow } \NC \xrightarrow [big] \NC \NR
-%D \NC \tex{xleftarrow } \NC \xleftarrow [big] \NC \NR
-%D \NC \tex{xequal } \NC \xequal [big] \NC \NR
-%D \NC \tex{xRightarrow } \NC \xRightarrow [big] \NC \NR
-%D \NC \tex{xLeftarrow } \NC \xLeftarrow [big] \NC \NR
-%D \NC \tex{xLeftrightarrow } \NC \xLeftrightarrow [big] \NC \NR
-%D \NC \tex{xleftrightarrow } \NC \xleftrightarrow [big] \NC \NR
-%D \NC \tex{xmapsto } \NC \xmapsto [big] \NC \NR
-%D \NC \tex{xtwoheadrightarrow } \NC \xtwoheadrightarrow [big] \NC \NR
-%D \NC \tex{xtwoheadleftarrow } \NC \xtwoheadleftarrow [big] \NC \NR
-%D \NC \tex{xrightharpoondown } \NC \xrightharpoondown [big] \NC \NR
-%D \NC \tex{xrightharpoonup } \NC \xrightharpoonup [big] \NC \NR
-%D \NC \tex{xleftharpoondown } \NC \xleftharpoondown [big] \NC \NR
-%D \NC \tex{xleftharpoonup } \NC \xleftharpoonup [big] \NC \NR
-%D \NC \tex{xhookleftarrow } \NC \xhookleftarrow [big] \NC \NR
-%D \NC \tex{xhookrightarrow } \NC \xhookrightarrow [big] \NC \NR
-%D \NC \tex{xleftrightharpoons } \NC \xleftrightharpoons [big] \NC \NR
-%D \NC \tex{xrightleftharpoons } \NC \xrightleftharpoons [big] \NC \NR
+%D \NC \tex{xrightarrow} \NC \xrightarrow [big] \NC \NR
+%D \NC \tex{xleftarrow} \NC \xleftarrow [big] \NC \NR
+%D \NC \tex{xequal} \NC \xequal [big] \NC \NR
+%D \NC \tex{xRightarrow} \NC \xRightarrow [big] \NC \NR
+%D \NC \tex{xLeftarrow} \NC \xLeftarrow [big] \NC \NR
+%D \NC \tex{xLeftrightarrow} \NC \xLeftrightarrow [big] \NC \NR
+%D \NC \tex{xleftrightarrow} \NC \xleftrightarrow [big] \NC \NR
+%D \NC \tex{xmapsto} \NC \xmapsto [big] \NC \NR
+%D \NC \tex{xtwoheadrightarrow} \NC \xtwoheadrightarrow [big] \NC \NR
+%D \NC \tex{xtwoheadleftarrow} \NC \xtwoheadleftarrow [big] \NC \NR
+%D \NC \tex{xrightharpoondown} \NC \xrightharpoondown [big] \NC \NR
+%D \NC \tex{xrightharpoonup} \NC \xrightharpoonup [big] \NC \NR
+%D \NC \tex{xleftharpoondown} \NC \xleftharpoondown [big] \NC \NR
+%D \NC \tex{xleftharpoonup} \NC \xleftharpoonup [big] \NC \NR
+%D \NC \tex{xhookleftarrow} \NC \xhookleftarrow [big] \NC \NR
+%D \NC \tex{xhookrightarrow} \NC \xhookrightarrow [big] \NC \NR
+%D \NC \tex{xleftrightharpoons} \NC \xleftrightharpoons [big] \NC \NR
+%D \NC \tex{xrightleftharpoons} \NC \xrightleftharpoons [big] \NC \NR
%D \stoptable}
+%D If needed this can be optimized (i.e. we can preexpand using \type
+%D {\docheckedpair}).
+
\unexpanded\def\definematharrow
- {\doquadrupleargument\dodefinematharrow}
+ {\doquadrupleargument\math_arrows_define}
-\def\dodefinematharrow[#1][#2][#3][#4]% name type[none|both] template command
+\def\math_arrows_define[#1][#2][#3][#4]% name type[none|both] template command
{\iffourthargument
- \executeifdefined{dodefine#2arrow}\gobblethreearguments{#1}{#3}{#4}%
+ \executeifdefined{math_arrows_define_#2}\gobblethreearguments{#1}{#3}{#4}%
\else\ifthirdargument
- \dodefinebotharrow{#1}{#2}{#3}%
+ \math_arrows_define_both{#1}{#2}{#3}%
\else\ifsecondargument
- \redefinebotharrow{#1}{#2}{#3}%
+ \math_arrows_define_both_again{#1}{#2}{#3}%
\fi\fi\fi}
-\def\redefinebotharrow#1#2#3% real dirty, this overload!
- {\doifdefined{#1}
- {\pushmacro\dohandlemtharrow
- \def\dohandlemtharrow[##1][##2]{\setuvalue{#1}{\dohandlemtharrow[#2][##2]}}%
- % == \def\dohandlemtharrow[##1][##2]{\dodefinebotharrow{#1}{#2}{##2}}%
- \getvalue{#1}%
- \popmacro\dohandlemtharrow}}
+\def\math_arrows_define_both_again#1#2#3% real dirty, this overload!
+ {\ifcsname#1\endcsname
+ \pushmacro\math_arrows_do
+ \def\math_arrows_do[##1][##2]{\setuvalue{#1}{\math_arrows_do[#2][##2]}}%
+ \getvalue{#1}%
+ \popmacro\math_arrows_do
+ \fi}
-\def\dodefinebotharrow#1#2#3%
- {\setuvalue{#1}{\dohandlemtharrow[#2][#3]}}
+\def\math_arrows_define_both#1#2#3%
+ {\setuvalue{#1}{\math_arrows_do[#2][#3]}}
-\def\dohandlemtharrow
- {\dotripleempty\doxmtharrow}
+\unexpanded\def\math_arrows_do
+ {\dotripleempty\math_arrows_handle}
-\def\doxmtharrow[#1][#2][#3]% #3 == optional arg
- {\def\dodoxmtharrow{\dododoxmtharrow[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2}
- \dodoublegroupempty\dodoxmtharrow}
+\def\math_arrows_handle[#1][#2][#3]% #3 == optional arg .. \empty can be just 'empty'
+ {\def\math_arrows_handle_indeed{\math_arrows_handle_finalize[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2}
+ \dodoublegroupempty\math_arrows_handle_indeed}
-\def\dododoxmtharrow[#1,#2,#3][#4,#5,#6][#7]#8#9% [3] is the optional arg
+\def\math_arrows_handle_finalize[#1,#2,#3][#4,#5,#6][#7]#8#9% [3] is the optional arg
{\edef\!!stringa{#2}%
\ifx\!!stringa\empty
\ifsecondargument
- \mathrel{\domthxarrsingle{#7}{#1}{#4}{#8}{#9}}%
+ \mathrel{\math_arrows_construct_single{#7}{#1}{#4}{#8}{#9}}%
\else
- \mathrel{\domthxarrsingle{#7}{#1}{#4}{}{#8}}%
+ \mathrel{\math_arrows_construct_single{#7}{#1}{#4}{}{#8}}%
\fi
\else
\ifsecondargument
- \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{#8}{#9}}%
+ \mathrel{\math_arrows_construct_double{#7}{#1}{#2}{#4}{#5}{#8}{#9}}%
\else
- \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{}{#8}}%
+ \mathrel{\math_arrows_construct_double{#7}{#1}{#2}{#4}{#5}{}{#8}}%
\fi
\fi}
@@ -324,40 +280,38 @@
%D \macros{mtharrowfill,defaultmtharrowfill}
%D
-%D To extend the arrows we need to define a \quotation{math arrow
-%D fill}. This command takes 8 arguments: the first four correspond
-%D the second argument of \tex{definematharrow} explained above. The
-%D other three specify the tail, body and head of the arrow. The last
-%D argument specifies the math-mode in which the arrow is drawn.
-%D \tex{defaultmtharrowfill} has values tweaked to match Latin Modern
-%D fonts. For fonts that are significantly different (e.g. cows) a
+%D To extend the arrows we need to define a \quotation {math arrow fill}. This
+%D command takes 8 arguments: the first four correspond the second argument of
+%D \tex {definematharrow} explained above. The other three specify the tail,
+%D body and head of the arrow. The last argument specifies the math-mode in which
+%D the arrow is drawn. \tex {defaultmtharrowfill} has values tweaked to match
+%D Latin Modern fonts. For fonts that are significantly different (e.g. cows) a
%D different set of values need to be determined.
\def\mtharrowfill#1#2#3#4#5#6#7#8%
- {$\mathsurround 0pt
- \thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip
+ {$\mathsurround\zeropoint
+ \thickmuskip\zeromuskip\medmuskip\thickmuskip\thinmuskip\thickmuskip
\relax#8#5%
- \mkern-#1mu
- \cleaders\hbox{$#8\mkern -#2mu#6\mkern -#3mu$}\hfill
- \mkern-#4mu#7$}
+ \mkern-#1\onemuskip
+ \cleaders\hbox{$#8\mkern-#2\onemuskip#6\mkern-#3\onemuskip$}\hfill
+ \mkern-#4\onemuskip#7$}
\def\defaultmtharrowfill{\mtharrowfill 7227}
-%D We now define some arrow fills that will be used for defining the
-%D arrows. Plain \TEX\ already defines \tex{leftarrowfill} and
-%D \tex{rightarrowfill}. The \tex{defaultmtharrowfill} command defines an
-%D arrowfill that takes an argument (so that it can also be used
-%D with over and under arrows). However the Plain \TEX\ definitions of
-%D \tex{leftarrowfill} and \tex{rightarrowfill} do not take this extra
-%D argument. To be backward compatible with Plain \TEX, we define two
-%D arrowfills: \tex{specrightarrowfill} which takes an extra argument, and
-%D \tex{rightarrowfill} which does not.
+%D We now define some arrow fills that will be used for defining the arrows. Plain
+%D \TEX\ already defines \tex {leftarrowfill} and \tex {rightarrowfill}. The \tex
+%D {defaultmtharrowfill} command defines an arrowfill that takes an argument (so
+%D that it can also be used with over and under arrows). However the Plain \TEX\
+%D definitions of \tex {leftarrowfill} and \tex {rightarrowfill} do not take this
+%D extra argument. To be backward compatible with Plain \TEX, we define two
+%D arrowfills: \tex {specrightarrowfill} which takes an extra argument, and \tex
+%D {rightarrowfill} which does not.
\unexpanded\def\specrightarrowfill {\defaultmtharrowfill \relbar \relbar \rightarrow}
\unexpanded\def\specleftarrowfill {\defaultmtharrowfill \leftarrow \relbar \relbar}
-\unexpanded\def\rightarrowfill {\specrightarrowfill \textstyle}
-\unexpanded\def\leftarrowfill {\specleftarrowfill \textstyle}
+\unexpanded\def\rightarrowfill {\specrightarrowfill \textstyle}
+\unexpanded\def\leftarrowfill {\specleftarrowfill \textstyle}
\unexpanded\def\equalfill {\defaultmtharrowfill \Relbar \Relbar \Relbar}
\unexpanded\def\Rightarrowfill {\defaultmtharrowfill \Relbar \Relbar \Rightarrow}
@@ -382,10 +336,27 @@
\unexpanded\def\doublebond{{\xequal}}
\unexpanded\def\triplebond{{\xtriplerel}}
-%D Now we define most commonly used arrows. These include arrows
-%D defined in \filename{amsmath.sty}, \filename{extarrows.sty},
-%D \filename{extpfel.sty} and \filename{mathtools.sty} packages for
-%D \LATEX\ (plus a few more).
+%D A bit or arrow juggling:
+%D
+%D \startbuffer
+%D \hbox to \hsize{\rightoverleftarrowfill}
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+
+\unexpanded\def\rightoverleftarrowfill
+ {\specrightoverleftarrowfill}
+
+\unexpanded\def\specrightoverleftarrowfill
+ {\defaultmtharrowfill
+ \ctxdoublearrowfillleftend
+ \ctxdoublearrowfillmiddlepart
+ \ctxdoublearrowfillrightend
+ \textstyle}
+
+%D Now we define most commonly used arrows. These include arrows defined in \filename
+%D {amsmath.sty}, \filename {extarrows.sty}, \filename {extpfel.sty} and \filename
+%D {mathtools.sty} packages for \LATEX\ (plus a few more).
\definematharrow [xrightarrow] [0359] [\specrightarrowfill]
\definematharrow [xleftarrow] [3095] [\specleftarrowfill]
@@ -427,27 +398,27 @@
%D \macros{definemathoverarrow,defineunderarrow}
%D
-%D These macros for define math-overarrows are adapted from
-%D \filename{amsmath.sty}
+%D These macros for define math-overarrows are adapted from \filename
+%D {amsmath.sty}
\unexpanded\def\definemathoverarrow
- {\dotripleargument\dodefinemathoverarrow}
+ {\dotripleargument\math_arrows_define_over}
-\def\dodefinemathoverarrow[#1][#2][#3]%
+\def\math_arrows_define_over[#1][#2][#3]%
{\ifthirdargument
- \setuvalue{#1}{\dohandlemathoverarrow[#2][#3]}%
+ \setuvalue{#1}{\math_arrows_over_handle[#2][#3]}%
\else
- \setuvalue{#1}{\dohandlemathoverarrow[\zeropoint][#2]}%
+ \setuvalue{#1}{\math_arrows_over_handle[\zeropoint][#2]}%
\fi}
-\def\dohandlemathoverarrow[#1][#2]%
- {\mathpalette{\dodohandlemathoverarrow{#1}{#2}}}
+\def\math_arrows_over_handle[#1][#2]%
+ {\mathpalette{\math_arrows_over_handle_indeed{#1}{#2}}}
-%D Note: \filename{math-pln.tex} has \type{\kern-\onepoint} and
-%D \filename{amsmath.sty} does not. We keep the kern amount
-%D configurable. This is useful for harpoons.
+%D Note: \filename {math-pln.tex} has \type {\kern-\onepoint} and \filename
+%D {amsmath.sty} does not. We keep the kern amount configurable. This is useful
+%D for harpoons.
-\def\dodohandlemathoverarrow#1#2#3#4%
+\def\math_arrows_over_handle_indeed#1#2#3#4%
{\vbox{\ialign{##\crcr
#2#3\crcr
\noalign{\kern#1\nointerlineskip}%
@@ -456,21 +427,21 @@
%D Now the under arrows
\unexpanded\def\definemathunderarrow
- {\dotripleargument\dodefinemathunderarrow}
+ {\dotripleargument\math_arrows_define_over}
%D For underarrows the default kern is 0.3ex
-\def\dodefinemathunderarrow[#1][#2][#3]%
+\def\math_arrows_define_over[#1][#2][#3]%
{\ifthirdargument
- \setuvalue{#1}{\dohandlemathunderarrow[#2][#3]}%
+ \setuvalue{#1}{\math_arrows_under_handle[#2][#3]}%
\else
- \setuvalue{#1}{\dohandlemathunderarrow[0.3ex][#2]}%
+ \setuvalue{#1}{\math_arrows_under_handle[0.3ex][#2]}%
\fi}
-\def\dohandlemathunderarrow[#1][#2]%
- {\mathpalette{\dodohandlemathunderarrow{#1}{#2}}}
+\def\math_arrows_under_handle[#1][#2]%
+ {\mathpalette{\math_arrows_under_handle_indeed{#1}{#2}}}
-\def\dodohandlemathunderarrow#1#2#3#4%
+\def\math_arrows_under_handle_indeed#1#2#3#4%
{\vtop{\ialign{##\crcr
$\mathsurround\zeropoint\hfil#3#4\hfil$\crcr
\noalign{\nointerlineskip\kern#1}%
diff --git a/tex/context/base/math-def.mkiv b/tex/context/base/math-def.mkiv
index 1c602187f..61153cfdd 100644
--- a/tex/context/base/math-def.mkiv
+++ b/tex/context/base/math-def.mkiv
@@ -119,7 +119,7 @@
\dorightbigmath#2\relax
\else
\doleftbigmath#2\relax
- \vbox\!!to\getvalue{\??mathbig\number#1}\bodyfontsize{}%
+ \vbox to\getvalue{\??mathbig\number#1}\bodyfontsize{}%
\dorightbigmath#2\relax
\fi
\nulldelimiterspace\zeropoint\relax
@@ -167,7 +167,8 @@
\unexpanded\def\implies {\mathrel{\;\Longrightarrow\;}}
\unexpanded\def\impliedby{\mathrel{\;\Longleftarrow\;}}
\unexpanded\def\And {\mathrel{\;\internalAnd\;}}
-\unexpanded\def\iff {\;\Longleftrightarrow\;}
+%unexpanded\def\iff {\;\Longleftrightarrow\;}
+\setuvalue {iff}{\;\Longleftrightarrow\;} % nicer for if checker
% todo: virtual in math-vfu
@@ -222,8 +223,9 @@
\definemathcommand [mathstrut] {\vphantom{(}}
\definemathcommand [joinrel] {\mathrel{\mkern-3mu}}
-\unexpanded\def\{{\mathortext\lbrace\letterleftbrace }
-\unexpanded\def\}{\mathortext\rbrace\letterrightbrace}
+\unexpanded\def\{{\mathortext\lbrace\letterleftbrace } % or maybe a chardef
+\unexpanded\def\}{\mathortext\rbrace\letterrightbrace} % or maybe a chardef
+\unexpanded\def\|{\mathortext\vert \letterbar } % or maybe a chardef
%D The following colon related definitions are provided by Aditya
%D Mahajan who derived them from \type {mathtools.sty} and \type
diff --git a/tex/context/base/math-dim.lua b/tex/context/base/math-dim.lua
index a5d7c3963..f4fc7905e 100644
--- a/tex/context/base/math-dim.lua
+++ b/tex/context/base/math-dim.lua
@@ -128,9 +128,9 @@ function mathematics.dimensions(dimens) -- beware, dimens get spoiled
return table.fastcopy(dimens), { }
elseif dimens.AxisHeight or dimens.axis_height then
local t = { }
- local math_x_height = dimens.x_height or 10*65526
- local math_quad = dimens.quad or 10*65526
- local default_rule_thickness = dimens.FractionDenominatorGapMin or dimens.default_rule_thickness or 0.4*65526
+ local math_x_height = dimens.x_height or 10*65536
+ local math_quad = dimens.quad or 10*65536
+ local default_rule_thickness = dimens.FractionDenominatorGapMin or dimens.default_rule_thickness or 0.4*65536
dimens["0"] = 0
dimens["60"] = 60
dimens["0.25*default_rule_thickness"] = default_rule_thickness / 4
diff --git a/tex/context/base/math-ext.lua b/tex/context/base/math-ext.lua
index da00c7a9e..047543970 100644
--- a/tex/context/base/math-ext.lua
+++ b/tex/context/base/math-ext.lua
@@ -20,8 +20,11 @@ characters.math = characters.math or { }
local mathdata = characters.math
local chardata = characters.data
-function extras.add(unicode,t)
+function extras.add(unicode,t) -- todo: if already stored ...
local min, max = mathematics.extrabase, mathematics.privatebase - 1
+ -- if mathdata[unicode] or chardata[unicode] then
+ -- report_math("extra U+%05X overloads existing character",unicode)
+ -- end
if unicode >= min and unicode <= max then
mathdata[unicode], chardata[unicode] = t, t
else
diff --git a/tex/context/base/math-fbk.lua b/tex/context/base/math-fbk.lua
new file mode 100644
index 000000000..b2b7ed5f0
--- /dev/null
+++ b/tex/context/base/math-fbk.lua
@@ -0,0 +1,281 @@
+if not modules then modules = { } end modules ['math-fbk'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local trace_fallbacks = false trackers.register("math.fallbacks", function(v) trace_fallbacks = v end)
+
+local report_fallbacks = logs.reporter("math","fallbacks")
+
+local fallbacks = { }
+mathematics.fallbacks = fallbacks
+
+local virtualcharacters = { }
+
+local identifiers = fonts.hashes.identifiers
+local lastmathids = fonts.hashes.lastmathids
+
+-- we need a trick (todo): if we define scriptscript, script and text in
+-- that order we could use their id's .. i.e. we could always add a font
+-- table with those id's .. in fact, we could also add a whole lot more
+-- as it doesn't hurt
+--
+-- todo: use index 'true when luatex provides that feature (on the agenda)
+
+function fallbacks.apply(target,original)
+ local mathparameters = target.mathparameters -- why not hasmath
+ if mathparameters then
+ local characters = target.characters
+ local parameters = target.parameters
+ local mathsize = parameters.mathsize
+ local size = parameters.size
+ local usedfonts = target.fonts
+ if not usedfonts then
+ usedfonts = { }
+ target.fonts = usedfonts
+ end
+ -- This is not okay yet ... we have no proper way to refer to 'self'
+ -- otherwise I will make my own id allocator).
+local self = #usedfonts == 0 and font.nextid() or nil -- will be true
+ local textid, scriptid, scriptscriptid
+ local textindex, scriptindex, scriptscriptindex
+ local textdata, scriptdata, scriptscriptdata
+ if mathsize == 3 then
+ -- scriptscriptsize
+ -- textid = nil -- self
+ -- scriptid = nil -- no smaller
+ -- scriptscriptid = nil -- no smaller
+textid = self
+scriptid = self
+scriptscriptid = self
+ elseif mathsize == 2 then
+ -- scriptsize
+ -- textid = nil -- self
+textid = self
+ scriptid = lastmathids[3]
+ scriptscriptid = lastmathids[3]
+ else
+ -- textsize
+ -- textid = nil -- self
+textid = self
+ scriptid = lastmathids[2]
+ scriptscriptid = lastmathids[3]
+ end
+ if textid then
+ textindex = #usedfonts + 1
+ usedfonts[textindex] = { id = textid }
+ textdata = identifiers[textid]
+ else
+ textdata = target
+ end
+ if scriptid then
+ scriptindex = #usedfonts + 1
+ usedfonts[scriptindex] = { id = scriptid }
+ scriptdata = identifiers[scriptid]
+ else
+ scriptindex = textindex
+ scriptdata = textdata
+ end
+ if scriptscriptid then
+ scriptscriptindex = #usedfonts + 1
+ usedfonts[scriptscriptindex] = { id = scriptscriptid }
+ scriptscriptdata = identifiers[scriptscriptid]
+ else
+ scriptscriptindex = scriptindex
+ scriptscriptdata = scriptdata
+ end
+-- report_fallbacks("used textid: %s, used script id: %s, used scriptscript id: %s",
+-- tostring(textid),tostring(scriptid),tostring(scriptscriptid))
+ local data = {
+ textdata = textdata,
+ scriptdata = scriptdata,
+ scriptscriptdata = scriptscriptdata,
+ textindex = textindex,
+ scriptindex = scriptindex,
+ scriptscriptindex = scriptscriptindex,
+ characters = characters,
+ unicode = k,
+ target = target,
+ original = original,
+ size = size,
+ mathsize = mathsize,
+ }
+-- inspect(usedfonts)
+ for k, v in next, virtualcharacters do
+ if not characters[k] then
+ local tv = type(v)
+ if tv == "table" then
+ characters[k] = v
+ elseif tv == "number" then
+ characters[k] = characters[v]
+ elseif tv == "function" then
+ characters[k] = v(data)
+ end
+ if trace_fallbacks then
+ if characters[k] then
+ report_fallbacks("extending font %q with U+%05X",target.properties.fullname,k)
+ end
+ end
+ end
+ end
+ end
+end
+
+utilities.sequencers.appendaction("aftercopyingcharacters","system","mathematics.fallbacks.apply")
+
+function fallbacks.install(unicode,value)
+ virtualcharacters[unicode] = value
+end
+
+-- a few examples:
+
+local function reference(index,char)
+ if index then
+ return { "slot", index, char }
+ else
+ return { "char", char }
+ end
+end
+
+local function raised(data,down)
+ local replacement = data.replacement
+ local character = data.scriptdata.characters[replacement]
+ if character then
+ return {
+ width = character.width,
+ height = character.height,
+ depth = character.depth,
+ commands = {
+ { "down", down and data.size/4 or -data.size/2 }, -- maybe exheight
+ reference(data.scriptindex,replacement)
+ }
+ }
+ end
+end
+
+-- virtualcharacters[0x207A] = 0x2212
+-- virtualcharacters[0x207B] = 0x002B
+-- virtualcharacters[0x208A] = 0x2212
+-- virtualcharacters[0x208B] = 0x002B
+
+virtualcharacters[0x207A] = function(data)
+ data.replacement = 0x2212
+ return raised(data)
+end
+
+virtualcharacters[0x207B] = function(data)
+ data.replacement = 0x002B
+ return raised(data)
+end
+
+virtualcharacters[0x208A] = function(data)
+ data.replacement = 0x2212
+ return raised(data,true)
+end
+
+virtualcharacters[0x208B] = function(data)
+ data.replacement = 0x002B
+ return raised(data,true)
+end
+
+local addextra = mathematics.extras.add
+
+addextra(0xFE350, {
+ category="sm",
+ description="MATHEMATICAL DOUBLE ARROW LEFT END",
+ mathclass="relation",
+ mathname="ctxdoublearrowfillleftend",
+ unicodeslot=0xFE350,
+} )
+
+addextra(0xFE351, {
+ category="sm",
+ description="MATHEMATICAL DOUBLE ARROW MIDDLE PART",
+ mathclass="relation",
+ mathname="ctxdoublearrowfillmiddlepart",
+ unicodeslot=0xFE351,
+} )
+
+addextra(0xFE352, {
+ category="sm",
+ description="MATHEMATICAL DOUBLE ARROW RIGHT END",
+ mathclass="relation",
+ mathname="ctxdoublearrowfillrightend",
+ unicodeslot=0xFE352,
+} )
+
+local push = { "push" }
+local pop = { "pop" }
+local leftarrow = { "char", 0x2190 }
+local relbar = { "char", 0x2212 }
+local rightarrow = { "char", 0x2192 }
+
+virtualcharacters[0xFE350] = function(data)
+ -- return combined(data,0x2190,0x2212) -- leftarrow relbar
+ local charone = data.characters[0x2190]
+ local chartwo = data.characters[0x2212]
+ if charone and chartwo then
+ local size = data.size/2
+ return {
+ width = chartwo.width,
+ height = size,
+ depth = size,
+ commands = {
+ push,
+ { "down", size/2 },
+ leftarrow,
+ pop,
+ { "down", -size/2 },
+ relbar,
+ }
+ }
+ end
+end
+
+virtualcharacters[0xFE351] = function(data)
+ -- return combined(data,0x2212,0x2212) -- relbar, relbar
+ local char = data.characters[0x2212]
+ if char then
+ local size = data.size/2
+ return {
+ width = char.width,
+ height = size,
+ depth = size,
+ commands = {
+ push,
+ { "down", size/2 },
+ relbar,
+ pop,
+ { "down", -size/2 },
+ relbar,
+ }
+ }
+ end
+end
+
+virtualcharacters[0xFE352] = function(data)
+ -- return combined(data,0x2192,0x2212) -- rightarrow relbar
+ local charone = data.characters[0x2192]
+ local chartwo = data.characters[0x2212]
+ if charone and chartwo then
+ local size = data.size/2
+ return {
+ width = chartwo.width,
+ height = size,
+ depth = size,
+ commands = {
+ push,
+ { "down", size/2 },
+ relbar,
+ pop,
+ { "right", chartwo.width - charone.width },
+ { "down", -size/2 },
+ rightarrow,
+ }
+ }
+ end
+end
+
diff --git a/tex/context/base/math-for.mkiv b/tex/context/base/math-for.mkiv
index aee640572..0c8bd05ae 100644
--- a/tex/context/base/math-for.mkiv
+++ b/tex/context/base/math-for.mkiv
@@ -30,19 +30,4 @@
\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/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua
index 54452282b..c84a92aee 100644
--- a/tex/context/base/math-ini.lua
+++ b/tex/context/base/math-ini.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['math-ext'] = {
+if not modules then modules = { } end modules ['math-ini'] = {
version = 1.001,
comment = "companion to math-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -33,6 +33,8 @@ local mathematics = mathematics
mathematics.extrabase = 0xFE000 -- here we push some virtuals
mathematics.privatebase = 0xFF000 -- here we push the ex
+local chardata = characters.data
+
local families = allocate {
mr = 0,
mb = 1,
@@ -63,6 +65,14 @@ local classes = allocate {
nolop = 1, -- mathnolopcomm @@mathnolopcomm
}
+local accents = allocate {
+ topaccent = true, [11] = true,
+ botaccent = true, [12] = true,
+ under = true, [13] = true,
+ over = true, [14] = true,
+ unknown = false,
+}
+
local codes = allocate {
ordinary = 0, [0] = "ordinary",
largeoperator = 1, [1] = "largeoperator",
@@ -76,6 +86,7 @@ local codes = allocate {
mathematics.classes = classes
mathematics.codes = codes
+-----------.accents = codes
mathematics.families = families
classes.alphabetic = classes.alpha
@@ -99,33 +110,43 @@ classes.number = classes.alphabetic
local function delcode(target,family,slot)
return format('\\Udelcode%s="%X "%X ',target,family,slot)
end
+
local function mathchar(class,family,slot)
return format('\\Umathchar "%X "%X "%X ',class,family,slot)
end
+
local function mathaccent(class,family,slot)
return format('\\Umathaccent "%X "%X "%X ',0,family,slot) -- no class
end
+
local function delimiter(class,family,slot)
return format('\\Udelimiter "%X "%X "%X ',class,family,slot)
end
+
local function radical(family,slot)
return format('\\Uradical "%X "%X ',family,slot)
end
+
local function mathchardef(name,class,family,slot)
return format('\\Umathchardef\\%s "%X "%X "%X ',name,class,family,slot)
end
+
local function mathcode(target,class,family,slot)
return format('\\Umathcode%s="%X "%X "%X ',target,class,family,slot)
end
+
local function mathtopaccent(class,family,slot)
return format('\\Umathaccent "%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
end
+
local function mathbotdelimiter(class,family,slot)
return format('\\Udelimiterunder "%X "%X ',family,slot) -- no class
end
@@ -156,72 +177,75 @@ if setmathcode then
setmathsymbol = function(name,class,family,slot) -- hex is nicer for tracing
if class == classes.accent then
- contextsprint(format([[\unexpanded\gdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot))
+ contextsprint(format([[\ugdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot))
elseif class == classes.topaccent then
- contextsprint(format([[\unexpanded\gdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot))
+ contextsprint(format([[\ugdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot))
elseif class == classes.botaccent then
- contextsprint(format([[\unexpanded\gdef\%s{\Umathbotaccent 0 "%X "%X }]],name,family,slot))
+ contextsprint(format([[\ugdef\%s{\Umathbotaccent 0 "%X "%X }]],name,family,slot))
elseif class == classes.over then
- contextsprint(format([[\unexpanded\gdef\%s{\Udelimiterover "%X "%X }]],name,family,slot))
+ contextsprint(format([[\ugdef\%s{\Udelimiterover "%X "%X }]],name,family,slot))
elseif class == classes.under then
- contextsprint(format([[\unexpanded\gdef\%s{\Udelimiterunder "%X "%X }]],name,family,slot))
+ contextsprint(format([[\ugdef\%s{\Udelimiterunder "%X "%X }]],name,family,slot))
elseif class == classes.open or class == classes.close then
setdelcode(slot,{family,slot,0,0})
- contextsprint(format([[\unexpanded\gdef\%s{\Udelimiter "%X "%X "%X }]],name,class,family,slot))
+ contextsprint(format([[\ugdef\%s{\Udelimiter "%X "%X "%X }]],name,class,family,slot))
elseif class == classes.delimiter then
setdelcode(slot,{family,slot,0,0})
- contextsprint(format([[\unexpanded\gdef\%s{\Udelimiter 0 "%X "%X }]],name,family,slot))
+ contextsprint(format([[\ugdef\%s{\Udelimiter 0 "%X "%X }]],name,family,slot))
elseif class == classes.radical then
- contextsprint(format([[\unexpanded\gdef\%s{\Uradical "%X "%X }]],name,family,slot))
+ contextsprint(format([[\ugdef\%s{\Uradical "%X "%X }]],name,family,slot))
else
-- beware, open/close and other specials should not end up here
--- contextsprint(format([[\unexpanded\gdef\%s{\Umathchar "%X "%X "%X }]],name,class,family,slot))
+ -- contextsprint(format([[\ugdef\%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)
- if class <= 7 then
- contextsprint(mathcode(slot,class,family,unicode or slot))
- end
- end
-
- 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
- contextsprint(delcode(slot,family,unicode))
- end
- end
-
- setmathsymbol = function(name,class,family,slot)
- if class == classes.accent then
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathaccent(class,family,slot)))
- elseif class == classes.topaccent then
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathtopaccent(class,family,slot)))
- elseif class == classes.botaccent then
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathbotaccent(class,family,slot)))
- elseif class == classes.over then
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathtopdelimiter(class,family,slot)))
- elseif class == classes.under then
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathbotdelimiter(class,family,slot)))
- elseif class == classes.open or class == classes.close then
- contextsprint(delcode(slot,family,slot))
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,delimiter(class,family,slot)))
- elseif class == classes.delimiter then
- contextsprint(delcode(slot,family,slot))
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,delimiter(0,family,slot)))
- elseif class == classes.radical then
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,radical(family,slot)))
- else
- -- beware, open/close and other specials should not end up here
- contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathchar(class,family,slot)))
- end
- end
+ report_math("your version of luatex is to old")
+
+ os.exit()
+
+ -- 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,setcode)
+ -- if setcode and class <= 7 then
+ -- contextsprint(mathcode(slot,class,family,unicode))
+ -- end
+ -- if class == classes.open or class == classes.close then
+ -- contextsprint(delcode(slot,family,unicode))
+ -- end
+ -- end
+ --
+ -- setmathsymbol = function(name,class,family,slot)
+ -- if class == classes.accent then
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,mathaccent(class,family,slot)))
+ -- elseif class == classes.topaccent then
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,mathtopaccent(class,family,slot)))
+ -- elseif class == classes.botaccent then
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,mathbotaccent(class,family,slot)))
+ -- elseif class == classes.over then
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,mathtopdelimiter(class,family,slot)))
+ -- elseif class == classes.under then
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,mathbotdelimiter(class,family,slot)))
+ -- elseif class == classes.open or class == classes.close then
+ -- contextsprint(delcode(slot,family,slot))
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,delimiter(class,family,slot)))
+ -- elseif class == classes.delimiter then
+ -- contextsprint(delcode(slot,family,slot))
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,delimiter(0,family,slot)))
+ -- elseif class == classes.radical then
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,radical(family,slot)))
+ -- else
+ -- -- beware, open/close and other specials should not end up here
+ -- contextsprint(format([[\uxdef\%s{%s}]],name,mathchar(class,family,slot)))
+ -- end
+ -- end
end
@@ -330,23 +354,29 @@ end
-- needed for mathml analysis
local function utfmathclass(chr, default)
- local cd = characters.data[utfbyte(chr)]
+ local cd = chardata[utfbyte(chr)]
return (cd and cd.mathclass) or default or "unknown"
end
+local function utfmathaccent(chr, default)
+ local cd = chardata[utfbyte(chr)]
+ local mc = cd and cd.mathclass or "unknown"
+ return mc and accents[mc] or false
+end
+
local function utfmathstretch(chr, default) -- "h", "v", "b", ""
- local cd = characters.data[utfbyte(chr)]
+ local cd = chardata[utfbyte(chr)]
return (cd and cd.mathstretch) or default or ""
end
local function utfmathcommand(chr, default)
- local cd = characters.data[utfbyte(chr)]
+ local cd = chardata[utfbyte(chr)]
local cmd = cd and cd.mathname
return cmd or default or ""
end
local function utfmathfiller(chr, default)
- local cd = characters.data[utfbyte(chr)]
+ local cd = chardata[utfbyte(chr)]
local cmd = cd and (cd.mathfiller or cd.mathname)
return cmd or default or ""
end
@@ -363,6 +393,9 @@ 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 commands.doifelseutfmathaccent(chr)
+ commands.doifelse(utfmathaccent(chr))
+end
-- helpers
diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv
index 710a65f5b..77441e092 100644
--- a/tex/context/base/math-ini.mkiv
+++ b/tex/context/base/math-ini.mkiv
@@ -27,14 +27,6 @@
\unprotect
-\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 \cldcontext{utf.char(948)}]]
@@ -45,10 +37,12 @@
\registerctxluafile{math-act}{1.001}
\registerctxluafile{math-ext}{1.001}
\registerctxluafile{math-vfu}{1.001}
+\registerctxluafile{math-ttv}{1.001}
\registerctxluafile{math-map}{1.001}
\registerctxluafile{math-ren}{1.001}
\registerctxluafile{math-noa}{1.001}
\registerctxluafile{math-tag}{1.001}
+\registerctxluafile{math-fbk}{1.001}
\definesystemattribute[mathalphabet] [public]
\definesystemattribute[mathsize] [public]
@@ -60,6 +54,8 @@
\definesystemattribute[mathmode] [public]
\definesystemattribute[mathitalics] [public]
+\definesystemattribute[displaymath] [public]
+
\appendtoks
\attribute\mathmodeattribute\plusone
\to \everydisplay
@@ -68,6 +64,10 @@
\attribute\mathmodeattribute\plusone
\to \everybeforedisplayformula
+\appendtoksonce
+ \attribute\displaymathattribute\plusone
+\to \everybeforedisplayformula
+
\setnewconstant\defaultmathfamily \zerocount % 255
%D Some measures (maybe spac-mth):
@@ -82,18 +82,6 @@
%D Configuration for integrals. (If needed we can speed this up and make it
%D installable; no processaction is needed then).
-% \newtoks\everysetupmathematics
-%
-% \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
@@ -265,13 +253,15 @@
\def\utfmathcommand#1{\ctxcommand{utfmathcommand(\!!bs#1\!!es)}}
\def\utfmathfiller #1{\ctxcommand{utfmathfiller (\!!bs#1\!!es)}}
+\unexpanded\def\doifelseutfmathaccent#1{\ctxcommand{doifelseutfmathaccent(\!!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}
+\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
@@ -857,15 +847,16 @@
\c_math_italics_attribute\csname\??mathitalics
\ifcsname\??mathitalics\p_italics\endcsname\p_italics\else\v!none\fi
\endcsname\relax
- \math_italics_initialize
+ % \math_italics_initialize
\to \everyswitchmathematics % only in mathematics
\appendtoks
+ \math_italics_initialize
\attribute\mathitalicsattribute\c_math_italics_attribute
\to \everymathematics
\setupmathematics
- [\s!italics=]
+ [\s!italics=4]
% looks nicer but can generate bogus csnames
%
diff --git a/tex/context/base/math-int.mkiv b/tex/context/base/math-int.mkiv
index 84c51cb24..8699cbc1c 100644
--- a/tex/context/base/math-int.mkiv
+++ b/tex/context/base/math-int.mkiv
@@ -38,7 +38,7 @@
\installcorenamespace{mathintegral}
-\newconstant\mathintlimitmode % 0 nolimits 1 displaylimits 2 limits
+\newconstant\mathintlimitmode
\def\intlimits % also used elsewhere
{\ifcase\mathintlimitmode
@@ -47,18 +47,29 @@
\displaylimits
\or
\limits
+ \or
+ % auto
+ \ifcase\normalmathstyle\displaylimits\or\displaylimits\else\limits\fi
+ % \ifnum\attribute\mathmodeattribute=\plusone % we need a proper flag
+ % \displaylimits
+ % \else
+ % \limits
+ % \fi
\fi}
\letvalue{\??mathintegral nolimits}\zerocount
\letvalue{\??mathintegral displaylimits}\plusone
\letvalue{\??mathintegral limits}\plustwo
+\letvalue{\??mathintegral autolimits}\plusthree
+\letvalue{\??mathintegral none}\plusfour
\appendtoks
\mathintlimitmode\executeifdefined{\??mathintegral\mathematicsparameter\s!integral}\zerocount
\to \everyswitchmathematics
\setupmathematics
- [\v!integral=nolimits]
+% [\v!integral=nolimits]
+ [\v!integral=autolimits]
%D The following code is used for fallbacks and might become obsolete once
%D we have enough \OPENTYPE\ math fonts.
diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua
index 8caf21cc2..6643a8758 100644
--- a/tex/context/base/math-noa.lua
+++ b/tex/context/base/math-noa.lua
@@ -56,11 +56,14 @@ 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 insert_node_before = node.insert_before
local free_node = node.free
local new_node = node.new -- todo: pool: math_noad math_sub
local new_kern = nodes.pool.kern
+local topoints = number.topoints
+
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
local fontcharacters = fonthashes.characters
@@ -103,6 +106,9 @@ local math_style = nodecodes.style -- attr style
local math_choice = nodecodes.choice -- attr display text script scriptscript
local math_fence = nodecodes.fence -- attr subtype
+local hlist_code = nodecodes.hlist
+local glyph_code = nodecodes.glyph
+
local left_fence_code = 1
local function process(start,what,n,parent)
@@ -758,61 +764,104 @@ 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 function getcorrection(method,font,char)
+
+ 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)
- elseif method == 3 then
- -- only quad based by selective
+ 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
- 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
+
+ if correction and correction ~= 0 then
+ return correction
+ end
+
+end
+
+local function insert_kern(current,kern)
+ local sub = new_node(math_sub) -- todo: pool
+ local noad = new_node(math_noad) -- todo: pool
+ sub.head = kern
+ kern.next = noad
+ noad.nucleus = current
+ return sub
+end
+
+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 = getcorrection(method,font,char)
+
+ -- maybe also correction when next == nil
+ -- when sub/sup -> already done
+
+ if correction then
+ if parent.id == math_noad and (parent.sub or parent.sup) then
+ if sub then
+ parent.sub = insert_kern(sub,new_kern(correction))
+ end
+ local sup = parent.sup
+ if sup then
+ parent.sup = insert_kern(sup,new_kern(correction))
+ end
+ else
+ local next_noad = parent.next
+ if not next_noad then
+ if true then -- this might become an option
+ if trace_italics then
+ report_italics("method %s: adding %s italic correction between %s (0x%05X) and end math",
+ method,number.points(correction),utfchar(char),char)
+ end
+ insert_node_after(parent,parent,new_kern(correction))
+ end
+ elseif 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
- insert_node_after(parent,parent,new_kern(correction))
end
end
end
@@ -821,7 +870,27 @@ italics[math_char] = function(pointer,what,n,parent)
end
end
+-- italics[math_noad] = function(pointer,what,n,parent)
+-- local nucleus = pointer.nucleus
+-- if nucleus.id == math_char then
+-- local method = has_attribute(pointer,a_mathitalics)
+-- if method and method > 0 then
+-- local char = nucleus.char
+-- local font = font_of_family(nucleus.fam) -- todo: table
+-- local correction = getcorrection(method,font,char)
+-- if correction then
+-- if trace_italics then
+-- report_italics("method %s: adding %s italic correction between %s (0x%05X) and script",
+-- method,number.points(correction),utfchar(char),char)
+-- end
+-- insert_node_after(nucleus,nucleus,new_kern(correction))
+-- end
+-- end
+-- end
+-- end
+
function handlers.italics(head,style,penalties)
+-- nodes.showsimplelist(head)
processnoads(head,italics,"italics")
return true
end
@@ -836,6 +905,66 @@ enable = function()
enable = false
end
+-- -- -- -- -- -- -- --
+-- -- -- -- -- -- -- --
+
+-- -- nice but not okay with multiple scripts (we need more clever hlist-shift checking then
+--
+-- local function processitalics(head,previous,previousmethod)
+-- local current = head
+-- while current do
+-- local id = current.id
+-- if id == glyph_code then
+-- local method = has_attribute(current,a_mathitalics)
+-- if method and method > 0 then -- keep method of previous
+-- if previous then
+-- local previousfont = previous.font
+-- local previouschar = previous.char
+-- local currentchar = current.char
+-- local correction = getcorrection(previousmethod,previousfont,previouschar)
+-- if correction then
+-- if trace_italics then
+-- report_italics("correction %s between U+%05X and U+%05X using method",topoints(correction),previouschar,currentchar,previousmethod)
+-- end
+-- insert_node_after(previous,previous,new_kern(correction))
+-- else
+-- if trace_italics then
+-- report_italics("no correction between U+%05X and U+%05X",previouschar,currentchar)
+-- end
+-- end
+-- end
+-- previous, previousmethod = current, method
+-- end
+-- elseif id == hlist_code then
+-- previous, previousmethod = processitalics(current.list,previous,previousmethod)
+-- elseif id == vlist_code then
+-- previous, previousmethod = processitalics(current.list,previous,previousmethod)
+-- else
+-- previous, previousmethod = nil
+-- end
+-- current = current.next
+-- end
+-- return previous, previousmethod
+-- end
+--
+-- function handlers.italics(head,style,penalties)
+-- processitalics(head)
+-- 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)
diff --git a/tex/context/base/math-ttv.lua b/tex/context/base/math-ttv.lua
new file mode 100644
index 000000000..be7d1949b
--- /dev/null
+++ b/tex/context/base/math-ttv.lua
@@ -0,0 +1,799 @@
+if not modules then modules = { } end modules ['math-ttv'] = {
+ version = 1.001,
+ comment = "traditional tex vectors, companion to math-vfu.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ dataonly = true,
+}
+
+local vfmath = fonts.handlers.vf.math
+local setletters = vfmath.setletters
+local setdigits = vfmath.setdigits
+
+local mathencodings = fonts.encodings.math
+
+-- varphi is part of the alphabet, contrary to the other var*s'
+
+mathencodings["large-to-small"] = {
+ [0x00028] = 0x00, -- (
+ [0x00029] = 0x01, -- )
+ [0x0005B] = 0x02, -- [
+ [0x0005D] = 0x03, -- ]
+ [0x0230A] = 0x04, -- lfloor
+ [0x0230B] = 0x05, -- rfloor
+ [0x02308] = 0x06, -- lceil
+ [0x02309] = 0x07, -- rceil
+ [0x0007B] = 0x08, -- {
+ [0x0007D] = 0x09, -- }
+ [0x027E8] = 0x0A, -- <
+ [0x027E9] = 0x0B, -- >
+ [0x0007C] = 0x0C, -- |
+--~ [0x0] = 0x0D, -- lVert rVert Vert
+-- [0x0002F] = 0x0E, -- /
+ [0x0005C] = 0x0F, -- \
+--~ [0x0] = 0x3A, -- lgroup
+--~ [0x0] = 0x3B, -- rgroup
+--~ [0x0] = 0x3C, -- arrowvert
+--~ [0x0] = 0x3D, -- Arrowvert
+ [0x02195] = 0x3F, -- updownarrow
+--~ [0x0] = 0x40, -- lmoustache
+--~ [0x0] = 0x41, -- rmoustache
+ [0x0221A] = 0x70, -- sqrt
+ [0x021D5] = 0x77, -- Updownarrow
+ [0x02191] = 0x78, -- uparrow
+ [0x02193] = 0x79, -- downarrow
+ [0x021D1] = 0x7E, -- Uparrow
+ [0x021D3] = 0x7F, -- Downarrow
+ [0x0220F] = 0x59, -- prod
+ [0x02210] = 0x61, -- coprod
+ [0x02211] = 0x58, -- sum
+ [0x0222B] = 0x5A, -- intop
+ [0x0222E] = 0x49, -- ointop
+ [0xFE302] = 0x62, -- widehat
+ [0xFE303] = 0x65, -- widetilde
+ [0x022C0] = 0x5E, -- bigwedge
+ [0x022C1] = 0x5F, -- bigvee
+ [0x022C2] = 0x5C, -- bigcap
+ [0x022C3] = 0x5B, -- bigcup
+ [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
+ [0x02210] = 0x60, -- coprod
+ [0x02211] = 0x50, -- sum
+ [0x0222B] = 0x52, -- intop
+ [0x0222E] = 0x48, -- ointop
+ [0x022C0] = 0x56, -- bigwedge
+ [0x022C1] = 0x57, -- bigvee
+ [0x022C2] = 0x54, -- bigcap
+ [0x022C3] = 0x53, -- bigcup
+ [0x02A00] = 0x4A, -- bigodot -- fixed BJ
+ [0x02A01] = 0x4C, -- bigoplus
+ [0x02A02] = 0x4E, -- bigotimes
+ -- [0x02A03] = , -- bigudot --
+ [0x02A04] = 0x55, -- biguplus
+ [0x02A06] = 0x46, -- bigsqcup
+}
+
+-- only math stuff is needed, since we always use an lm or gyre
+-- font as main font
+
+mathencodings["tex-mr"] = {
+ [0x00393] = 0x00, -- Gamma
+ [0x00394] = 0x01, -- Delta
+ [0x00398] = 0x02, -- Theta
+ [0x0039B] = 0x03, -- Lambda
+ [0x0039E] = 0x04, -- Xi
+ [0x003A0] = 0x05, -- Pi
+ [0x003A3] = 0x06, -- Sigma
+ [0x003A5] = 0x07, -- Upsilon
+ [0x003A6] = 0x08, -- Phi
+ [0x003A8] = 0x09, -- Psi
+ [0x003A9] = 0x0A, -- Omega
+-- [0x00060] = 0x12, -- [math]grave
+-- [0x000B4] = 0x13, -- [math]acute
+-- [0x002C7] = 0x14, -- [math]check
+-- [0x002D8] = 0x15, -- [math]breve
+-- [0x000AF] = 0x16, -- [math]bar
+-- [0x00021] = 0x21, -- !
+-- [0x00028] = 0x28, -- (
+-- [0x00029] = 0x29, -- )
+-- [0x0002B] = 0x2B, -- +
+-- [0x0002F] = 0x2F, -- /
+-- [0x0003A] = 0x3A, -- :
+-- [0x02236] = 0x3A, -- colon
+-- [0x0003B] = 0x3B, -- ;
+-- [0x0003C] = 0x3C, -- <
+-- [0x0003D] = 0x3D, -- =
+-- [0x0003E] = 0x3E, -- >
+-- [0x0003F] = 0x3F, -- ?
+ [0x00391] = 0x41, -- Alpha
+ [0x00392] = 0x42, -- Beta
+ [0x02145] = 0x44,
+ [0x00395] = 0x45, -- Epsilon
+ [0x00397] = 0x48, -- Eta
+ [0x00399] = 0x49, -- Iota
+ [0x0039A] = 0x4B, -- Kappa
+ [0x0039C] = 0x4D, -- Mu
+ [0x0039D] = 0x4E, -- Nu
+ [0x0039F] = 0x4F, -- Omicron
+ [0x003A1] = 0x52, -- Rho
+ [0x003A4] = 0x54, -- Tau
+ [0x003A7] = 0x58, -- Chi
+ [0x00396] = 0x5A, -- Zeta
+-- [0x0005B] = 0x5B, -- [
+-- [0x0005D] = 0x5D, -- ]
+-- [0x0005E] = 0x5E, -- [math]hat -- the text one
+ [0x00302] = 0x5E, -- [math]hat -- the real math one
+-- [0x002D9] = 0x5F, -- [math]dot
+ [0x02146] = 0x64,
+ [0x02147] = 0x65,
+-- [0x002DC] = 0x7E, -- [math]tilde -- the text one
+ [0x00303] = 0x7E, -- [math]tilde -- the real one
+-- [0x000A8] = 0x7F, -- [math]ddot
+}
+
+mathencodings["tex-mr-missing"] = {
+ [0x02236] = 0x3A, -- colon
+}
+
+mathencodings["tex-mi"] = {
+ [0x1D6E4] = 0x00, -- Gamma
+ [0x1D6E5] = 0x01, -- Delta
+ [0x1D6E9] = 0x02, -- Theta
+ [0x1D6F3] = 0x02, -- varTheta (not present in TeX)
+ [0x1D6EC] = 0x03, -- Lambda
+ [0x1D6EF] = 0x04, -- Xi
+ [0x1D6F1] = 0x05, -- Pi
+ [0x1D6F4] = 0x06, -- Sigma
+ [0x1D6F6] = 0x07, -- Upsilon
+ [0x1D6F7] = 0x08, -- Phi
+ [0x1D6F9] = 0x09, -- Psi
+ [0x1D6FA] = 0x0A, -- Omega
+ [0x1D6FC] = 0x0B, -- alpha
+ [0x1D6FD] = 0x0C, -- beta
+ [0x1D6FE] = 0x0D, -- gamma
+ [0x1D6FF] = 0x0E, -- delta
+ [0x1D716] = 0x0F, -- epsilon TODO: 1D716
+ [0x1D701] = 0x10, -- zeta
+ [0x1D702] = 0x11, -- eta
+ [0x1D703] = 0x12, -- theta TODO: 1D703
+ [0x1D704] = 0x13, -- iota
+ [0x1D705] = 0x14, -- kappa
+ [0x1D718] = 0x14, -- varkappa, not in tex fonts
+ [0x1D706] = 0x15, -- lambda
+ [0x1D707] = 0x16, -- mu
+ [0x1D708] = 0x17, -- nu
+ [0x1D709] = 0x18, -- xi
+ [0x1D70B] = 0x19, -- pi
+ [0x1D70C] = 0x1A, -- rho
+ [0x1D70E] = 0x1B, -- sigma
+ [0x1D70F] = 0x1C, -- tau
+ [0x1D710] = 0x1D, -- upsilon
+ [0x1D719] = 0x1E, -- phi
+ [0x1D712] = 0x1F, -- chi
+ [0x1D713] = 0x20, -- psi
+ [0x1D714] = 0x21, -- omega
+ [0x1D700] = 0x22, -- varepsilon (the other way around)
+ [0x1D717] = 0x23, -- vartheta
+ [0x1D71B] = 0x24, -- varpi
+ [0x1D71A] = 0x25, -- varrho
+ [0x1D70D] = 0x26, -- varsigma
+ [0x1D711] = 0x27, -- varphi (the other way around)
+ [0x021BC] = 0x28, -- leftharpoonup
+ [0x021BD] = 0x29, -- leftharpoondown
+ [0x021C0] = 0x2A, -- rightharpoonup
+ [0x021C1] = 0x2B, -- rightharpoondown
+ [0xFE322] = 0x2C, -- lhook (hook for combining arrows)
+ [0xFE323] = 0x2D, -- rhook (hook for combining arrows)
+ [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
+-- [0x00041] = 0x33, -- 3
+-- [0x00041] = 0x34, -- 4
+-- [0x00041] = 0x35, -- 5
+-- [0x00041] = 0x36, -- 6
+-- [0x00041] = 0x37, -- 7
+-- [0x00041] = 0x38, -- 8
+-- [0x00041] = 0x39, -- 9
+--~ [0x0002E] = 0x3A, -- .
+ [0x0002C] = 0x3B, -- ,
+ [0x0003C] = 0x3C, -- <
+-- [0x0002F] = 0x3D, -- /, slash, solidus
+ [0x02044] = 0x3D, -- / AM: Not sure
+ [0x0003E] = 0x3E, -- >
+ [0x022C6] = 0x3F, -- star
+ [0x02202] = 0x40, -- partial
+--
+ [0x0266D] = 0x5B, -- flat
+ [0x0266E] = 0x5C, -- natural
+ [0x0266F] = 0x5D, -- sharp
+ [0x02323] = 0x5E, -- smile
+ [0x02322] = 0x5F, -- frown
+ [0x02113] = 0x60, -- ell
+--
+ [0x1D6A4] = 0x7B, -- imath (TODO: also 0131)
+ [0x1D6A5] = 0x7C, -- jmath (TODO: also 0237)
+ [0x02118] = 0x7D, -- wp
+ [0x020D7] = 0x7E, -- vec (TODO: not sure)
+-- 0x7F, -- (no idea what that could be)
+}
+
+mathencodings["tex-it"] = {
+-- [0x1D434] = 0x41, -- A
+ [0x1D6E2] = 0x41, -- Alpha
+-- [0x1D435] = 0x42, -- B
+ [0x1D6E3] = 0x42, -- Beta
+-- [0x1D436] = 0x43, -- C
+-- [0x1D437] = 0x44, -- D
+-- [0x1D438] = 0x45, -- E
+ [0x1D6E6] = 0x45, -- Epsilon
+-- [0x1D439] = 0x46, -- F
+-- [0x1D43A] = 0x47, -- G
+-- [0x1D43B] = 0x48, -- H
+ [0x1D6E8] = 0x48, -- Eta
+-- [0x1D43C] = 0x49, -- I
+ [0x1D6EA] = 0x49, -- Iota
+-- [0x1D43D] = 0x4A, -- J
+-- [0x1D43E] = 0x4B, -- K
+ [0x1D6EB] = 0x4B, -- Kappa
+-- [0x1D43F] = 0x4C, -- L
+-- [0x1D440] = 0x4D, -- M
+ [0x1D6ED] = 0x4D, -- Mu
+-- [0x1D441] = 0x4E, -- N
+ [0x1D6EE] = 0x4E, -- Nu
+-- [0x1D442] = 0x4F, -- O
+ [0x1D6F0] = 0x4F, -- Omicron
+-- [0x1D443] = 0x50, -- P
+ [0x1D6F2] = 0x50, -- Rho
+-- [0x1D444] = 0x51, -- Q
+-- [0x1D445] = 0x52, -- R
+-- [0x1D446] = 0x53, -- S
+-- [0x1D447] = 0x54, -- T
+ [0x1D6F5] = 0x54, -- Tau
+-- [0x1D448] = 0x55, -- U
+-- [0x1D449] = 0x56, -- V
+-- [0x1D44A] = 0x57, -- W
+-- [0x1D44B] = 0x58, -- X
+ [0x1D6F8] = 0x58, -- Chi
+-- [0x1D44C] = 0x59, -- Y
+-- [0x1D44D] = 0x5A, -- Z
+--
+-- [0x1D44E] = 0x61, -- a
+-- [0x1D44F] = 0x62, -- b
+-- [0x1D450] = 0x63, -- c
+-- [0x1D451] = 0x64, -- d
+-- [0x1D452] = 0x65, -- e
+-- [0x1D453] = 0x66, -- f
+-- [0x1D454] = 0x67, -- g
+-- [0x1D455] = 0x68, -- h
+ [0x0210E] = 0x68, -- Planck constant (h)
+-- [0x1D456] = 0x69, -- i
+-- [0x1D457] = 0x6A, -- j
+-- [0x1D458] = 0x6B, -- k
+-- [0x1D459] = 0x6C, -- l
+-- [0x1D45A] = 0x6D, -- m
+-- [0x1D45B] = 0x6E, -- n
+-- [0x1D45C] = 0x6F, -- o
+ [0x1D70A] = 0x6F, -- omicron
+-- [0x1D45D] = 0x70, -- p
+-- [0x1D45E] = 0x71, -- q
+-- [0x1D45F] = 0x72, -- r
+-- [0x1D460] = 0x73, -- s
+-- [0x1D461] = 0x74, -- t
+-- [0x1D462] = 0x75, -- u
+-- [0x1D463] = 0x76, -- v
+-- [0x1D464] = 0x77, -- w
+-- [0x1D465] = 0x78, -- x
+-- [0x1D466] = 0x79, -- y
+-- [0x1D467] = 0x7A, -- z
+}
+
+mathencodings["tex-ss"] = { }
+mathencodings["tex-tt"] = { }
+mathencodings["tex-bf"] = { }
+mathencodings["tex-bi"] = { }
+mathencodings["tex-fraktur"] = { }
+mathencodings["tex-fraktur-bold"] = { }
+
+mathencodings["tex-sy"] = {
+ [0x0002D] = 0x00, -- -
+ [0x02212] = 0x00, -- -
+-- [0x02201] = 0x00, -- complement
+-- [0x02206] = 0x00, -- increment
+-- [0x02204] = 0x00, -- not exists
+-- [0x000B7] = 0x01, -- cdot
+ [0x022C5] = 0x01, -- cdot
+ [0x000D7] = 0x02, -- times
+ [0x0002A] = 0x03, -- *
+ [0x02217] = 0x03, -- *
+ [0x000F7] = 0x04, -- div
+ [0x022C4] = 0x05, -- diamond
+ [0x000B1] = 0x06, -- pm
+ [0x02213] = 0x07, -- mp
+ [0x02295] = 0x08, -- oplus
+ [0x02296] = 0x09, -- ominus
+ [0x02297] = 0x0A, -- otimes
+ [0x02298] = 0x0B, -- oslash
+ [0x02299] = 0x0C, -- odot
+ [0x025EF] = 0x0D, -- bigcirc, Orb (either 25EF or 25CB) -- todo
+ [0x02218] = 0x0E, -- circ
+ [0x02219] = 0x0F, -- bullet
+ [0x02022] = 0x0F, -- bullet
+ [0x0224D] = 0x10, -- asymp
+ [0x02261] = 0x11, -- equiv
+ [0x02286] = 0x12, -- subseteq
+ [0x02287] = 0x13, -- supseteq
+ [0x02264] = 0x14, -- leq
+ [0x02265] = 0x15, -- geq
+ [0x02AAF] = 0x16, -- preceq
+-- [0x0227C] = 0x16, -- preceq, AM:No see 2AAF
+ [0x02AB0] = 0x17, -- succeq
+-- [0x0227D] = 0x17, -- succeq, AM:No see 2AB0
+ [0x0223C] = 0x18, -- sim
+ [0x02248] = 0x19, -- approx
+ [0x02282] = 0x1A, -- subset
+ [0x02283] = 0x1B, -- supset
+ [0x0226A] = 0x1C, -- ll
+ [0x0226B] = 0x1D, -- gg
+ [0x0227A] = 0x1E, -- prec
+ [0x0227B] = 0x1F, -- succ
+ [0x02190] = 0x20, -- leftarrow
+ [0x02192] = 0x21, -- rightarrow
+--~ [0xFE190] = 0x20, -- leftarrow
+--~ [0xFE192] = 0x21, -- rightarrow
+ [0x02191] = 0x22, -- uparrow
+ [0x02193] = 0x23, -- downarrow
+ [0x02194] = 0x24, -- leftrightarrow
+ [0x02197] = 0x25, -- nearrow
+ [0x02198] = 0x26, -- searrow
+ [0x02243] = 0x27, -- simeq
+ [0x021D0] = 0x28, -- Leftarrow
+ [0x021D2] = 0x29, -- Rightarrow
+ [0x021D1] = 0x2A, -- Uparrow
+ [0x021D3] = 0x2B, -- Downarrow
+ [0x021D4] = 0x2C, -- Leftrightarrow
+ [0x02196] = 0x2D, -- nwarrow
+ [0x02199] = 0x2E, -- swarrow
+ [0x0221D] = 0x2F, -- propto
+ [0x02032] = 0x30, -- prime
+ [0x0221E] = 0x31, -- infty
+ [0x02208] = 0x32, -- in
+ [0x0220B] = 0x33, -- ni
+ [0x025B3] = 0x34, -- triangle, bigtriangleup
+ [0x025BD] = 0x35, -- bigtriangledown
+ [0x00338] = 0x36, -- not
+-- 0x37, -- (beginning of arrow)
+ [0x02200] = 0x38, -- forall
+ [0x02203] = 0x39, -- exists
+ [0x000AC] = 0x3A, -- neg, lnot
+ [0x02205] = 0x3B, -- empty set
+ [0x0211C] = 0x3C, -- Re
+ [0x02111] = 0x3D, -- Im
+ [0x022A4] = 0x3E, -- top
+ [0x022A5] = 0x3F, -- bot, perp
+ [0x02135] = 0x40, -- aleph
+ [0x1D49C] = 0x41, -- script A
+ [0x0212C] = 0x42, -- script B
+ [0x1D49E] = 0x43, -- script C
+ [0x1D49F] = 0x44, -- script D
+ [0x02130] = 0x45, -- script E
+ [0x02131] = 0x46, -- script F
+ [0x1D4A2] = 0x47, -- script G
+ [0x0210B] = 0x48, -- script H
+ [0x02110] = 0x49, -- script I
+ [0x1D4A5] = 0x4A, -- script J
+ [0x1D4A6] = 0x4B, -- script K
+ [0x02112] = 0x4C, -- script L
+ [0x02133] = 0x4D, -- script M
+ [0x1D4A9] = 0x4E, -- script N
+ [0x1D4AA] = 0x4F, -- script O
+ [0x1D4AB] = 0x50, -- script P
+ [0x1D4AC] = 0x51, -- script Q
+ [0x0211B] = 0x52, -- script R
+ [0x1D4AE] = 0x53, -- script S
+ [0x1D4AF] = 0x54, -- script T
+ [0x1D4B0] = 0x55, -- script U
+ [0x1D4B1] = 0x56, -- script V
+ [0x1D4B2] = 0x57, -- script W
+ [0x1D4B3] = 0x58, -- script X
+ [0x1D4B4] = 0x59, -- script Y
+ [0x1D4B5] = 0x5A, -- script Z
+ [0x0222A] = 0x5B, -- cup
+ [0x02229] = 0x5C, -- cap
+ [0x0228E] = 0x5D, -- uplus
+ [0x02227] = 0x5E, -- wedge, land
+ [0x02228] = 0x5F, -- vee, lor
+ [0x022A2] = 0x60, -- vdash
+ [0x022A3] = 0x61, -- dashv
+ [0x0230A] = 0x62, -- lfloor
+ [0x0230B] = 0x63, -- rfloor
+ [0x02308] = 0x64, -- lceil
+ [0x02309] = 0x65, -- rceil
+ [0x0007B] = 0x66, -- {, lbrace
+ [0x0007D] = 0x67, -- }, rbrace
+ [0x027E8] = 0x68, -- <, langle
+ [0x027E9] = 0x69, -- >, rangle
+ [0x0007C] = 0x6A, -- |, mid, lvert, rvert
+ [0x02225] = 0x6B, -- parallel
+ -- [0x02016] = 0x00, -- Vert, lVert, rVert, arrowvert, Arrowvert
+ [0x02195] = 0x6C, -- updownarrow
+ [0x021D5] = 0x6D, -- Updownarrow
+ [0x0005C] = 0x6E, -- \, backslash, setminus
+ [0x02216] = 0x6E, -- setminus
+ [0x02240] = 0x6F, -- wr
+ [0x0221A] = 0x70, -- sqrt. AM: Check surd??
+ [0x02A3F] = 0x71, -- amalg
+ [0x1D6FB] = 0x72, -- nabla
+-- [0x0222B] = 0x73, -- smallint (TODO: what about intop?)
+ [0x02294] = 0x74, -- sqcup
+ [0x02293] = 0x75, -- sqcap
+ [0x02291] = 0x76, -- sqsubseteq
+ [0x02292] = 0x77, -- sqsupseteq
+ [0x000A7] = 0x78, -- S
+ [0x02020] = 0x79, -- dagger, dag
+ [0x02021] = 0x7A, -- ddagger, ddag
+ [0x000B6] = 0x7B, -- P
+ [0x02663] = 0x7C, -- clubsuit
+ [0x02662] = 0x7D, -- diamondsuit
+ [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
+-- column, while in the second column we show the tex/ams names. As usual
+-- it costs hours to figure out such a table.
+
+mathencodings["tex-ma"] = {
+ [0x022A1] = 0x00, -- squaredot \boxdot
+ [0x0229E] = 0x01, -- squareplus \boxplus
+ [0x022A0] = 0x02, -- squaremultiply \boxtimes
+ [0x025A1] = 0x03, -- square \square \Box
+ [0x025A0] = 0x04, -- squaresolid \blacksquare
+ [0x025AA] = 0x05, -- squaresmallsolid \centerdot
+ [0x022C4] = 0x06, -- diamond \Diamond \lozenge
+ [0x02666] = 0x07, -- diamondsolid \blacklozenge
+ [0x021BB] = 0x08, -- clockwise \circlearrowright
+ [0x021BA] = 0x09, -- anticlockwise \circlearrowleft
+ [0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons
+ [0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons
+ [0x0229F] = 0x0C, -- squareminus \boxminus
+ [0x022A9] = 0x0D, -- forces \Vdash
+ [0x022AA] = 0x0E, -- forcesbar \Vvdash
+ [0x022A8] = 0x0F, -- satisfies \vDash
+ [0x021A0] = 0x10, -- dblarrowheadright \twoheadrightarrow
+ [0x0219E] = 0x11, -- dblarrowheadleft \twoheadleftarrow
+ [0x021C7] = 0x12, -- dblarrowleft \leftleftarrows
+ [0x021C9] = 0x13, -- dblarrowright \rightrightarrows
+ [0x021C8] = 0x14, -- dblarrowup \upuparrows
+ [0x021CA] = 0x15, -- dblarrowdwn \downdownarrows
+ [0x021BE] = 0x16, -- harpoonupright \upharpoonright \restriction
+ [0x021C2] = 0x17, -- harpoondownright \downharpoonright
+ [0x021BF] = 0x18, -- harpoonupleft \upharpoonleft
+ [0x021C3] = 0x19, -- harpoondownleft \downharpoonleft
+ [0x021A3] = 0x1A, -- arrowtailright \rightarrowtail
+ [0x021A2] = 0x1B, -- arrowtailleft \leftarrowtail
+ [0x021C6] = 0x1C, -- arrowparrleftright \leftrightarrows
+-- [0x021C5] = 0x00, -- \updownarrows (missing in lm)
+ [0x021C4] = 0x1D, -- arrowparrrightleft \rightleftarrows
+ [0x021B0] = 0x1E, -- shiftleft \Lsh
+ [0x021B1] = 0x1F, -- shiftright \Rsh
+ [0x021DD] = 0x20, -- squiggleright \leadsto \rightsquigarrow
+ [0x021AD] = 0x21, -- squiggleleftright \leftrightsquigarrow
+ [0x021AB] = 0x22, -- curlyleft \looparrowleft
+ [0x021AC] = 0x23, -- curlyright \looparrowright
+ [0x02257] = 0x24, -- circleequal \circeq
+ [0x0227F] = 0x25, -- followsorequal \succsim
+ [0x02273] = 0x26, -- greaterorsimilar \gtrsim
+ [0x02A86] = 0x27, -- greaterorapproxeql \gtrapprox
+ [0x022B8] = 0x28, -- multimap \multimap
+ [0x02234] = 0x29, -- therefore \therefore
+ [0x02235] = 0x2A, -- because \because
+ [0x02251] = 0x2B, -- equalsdots \Doteq \doteqdot
+ [0x0225C] = 0x2C, -- defines \triangleq
+ [0x0227E] = 0x2D, -- precedesorequal \precsim
+ [0x02272] = 0x2E, -- lessorsimilar \lesssim
+ [0x02A85] = 0x2F, -- lessorapproxeql \lessapprox
+ [0x02A95] = 0x30, -- equalorless \eqslantless
+ [0x02A96] = 0x31, -- equalorgreater \eqslantgtr
+ [0x022DE] = 0x32, -- equalorprecedes \curlyeqprec
+ [0x022DF] = 0x33, -- equalorfollows \curlyeqsucc
+ [0x0227C] = 0x34, -- precedesorcurly \preccurlyeq
+ [0x02266] = 0x35, -- lessdblequal \leqq
+ [0x02A7D] = 0x36, -- lessorequalslant \leqslant
+ [0x02276] = 0x37, -- lessorgreater \lessgtr
+ [0x02035] = 0x38, -- primereverse \backprime
+ -- [0x0] = 0x39, -- axisshort \dabar
+ [0x02253] = 0x3A, -- equaldotrightleft \risingdotseq
+ [0x02252] = 0x3B, -- equaldotleftright \fallingdotseq
+ [0x0227D] = 0x3C, -- followsorcurly \succcurlyeq
+ [0x02267] = 0x3D, -- greaterdblequal \geqq
+ [0x02A7E] = 0x3E, -- greaterorequalslant \geqslant
+ [0x02277] = 0x3F, -- greaterorless \gtrless
+ [0x0228F] = 0x40, -- squareimage \sqsubset
+ [0x02290] = 0x41, -- squareoriginal \sqsupset
+ -- wrong: see **
+ -- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright
+ -- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft
+ -- cf lm
+ [0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq
+ [0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq
+ --
+ [0x02605] = 0x46, -- star \bigstar
+ [0x0226C] = 0x47, -- between \between
+ [0x025BC] = 0x48, -- triangledownsld \blacktriangledown
+ [0x025B6] = 0x49, -- trianglerightsld \blacktriangleright
+ [0x025C0] = 0x4A, -- triangleleftsld \blacktriangleleft
+ -- [0x0] = 0x4B, -- arrowaxisright
+ -- [0x0] = 0x4C, -- arrowaxisleft
+ [0x025B2] = 0x4D, -- triangle \triangleup \vartriangle
+ [0x025B2] = 0x4E, -- trianglesolid \blacktriangle
+ [0x025BD] = 0x4F, -- triangleinv \triangledown
+ [0x02256] = 0x50, -- ringinequal \eqcirc
+ [0x022DA] = 0x51, -- lessequalgreater \lesseqgtr
+ [0x022DB] = 0x52, -- greaterlessequal \gtreqless
+ [0x02A8B] = 0x53, -- lessdbleqlgreater \lesseqqgtr
+ [0x02A8C] = 0x54, -- greaterdbleqlless \gtreqqless
+ [0x000A5] = 0x55, -- Yen \yen
+ [0x021DB] = 0x56, -- arrowtripleright \Rrightarrow
+ [0x021DA] = 0x57, -- arrowtripleleft \Lleftarrow
+ [0x02713] = 0x58, -- check \checkmark
+ [0x022BB] = 0x59, -- orunderscore \veebar
+ [0x022BC] = 0x5A, -- nand \barwedge
+ [0x02306] = 0x5B, -- perpcorrespond \doublebarwedge
+ [0x02220] = 0x5C, -- angle \angle
+ [0x02221] = 0x5D, -- measuredangle \measuredangle
+ [0x02222] = 0x5E, -- sphericalangle \sphericalangle
+ -- [0x0] = 0x5F, -- proportional \varpropto
+ -- [0x0] = 0x60, -- smile \smallsmile
+ -- [0x0] = 0x61, -- frown \smallfrown
+ [0x022D0] = 0x62, -- subsetdbl \Subset
+ [0x022D1] = 0x63, -- supersetdbl \Supset
+ [0x022D3] = 0x64, -- uniondbl \doublecup \Cup
+ [0x022D2] = 0x65, -- intersectiondbl \doublecap \Cap
+ [0x022CF] = 0x66, -- uprise \curlywedge
+ [0x022CE] = 0x67, -- downfall \curlyvee
+ [0x022CB] = 0x68, -- multiopenleft \leftthreetimes
+ [0x022CC] = 0x69, -- multiopenright \rightthreetimes
+ [0x02AC5] = 0x6A, -- subsetdblequal \subseteqq
+ [0x02AC6] = 0x6B, -- supersetdblequal \supseteqq
+ [0x0224F] = 0x6C, -- difference \bumpeq
+ [0x0224E] = 0x6D, -- geomequivalent \Bumpeq
+ [0x022D8] = 0x6E, -- muchless \lll \llless
+ [0x022D9] = 0x6F, -- muchgreater \ggg \gggtr
+ [0x0231C] = 0x70, -- rightanglenw \ulcorner
+ [0x0231D] = 0x71, -- rightanglene \urcorner
+ [0x024C7] = 0x72, -- circleR \circledR
+ [0x024C8] = 0x73, -- circleS \circledS
+ [0x022D4] = 0x74, -- fork \pitchfork
+ [0x02214] = 0x75, -- dotplus \dotplus
+ [0x0223D] = 0x76, -- revsimilar \backsim
+ [0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq.
+ [0x0231E] = 0x78, -- rightanglesw \llcorner
+ [0x0231F] = 0x79, -- rightanglese \lrcorner
+ [0x02720] = 0x7A, -- maltesecross \maltese
+ [0x02201] = 0x7B, -- complement \complement
+ [0x022BA] = 0x7C, -- intercal \intercal
+ [0x0229A] = 0x7D, -- circlering \circledcirc
+ [0x0229B] = 0x7E, -- circleasterisk \circledast
+ [0x0229D] = 0x7F, -- circleminus \circleddash
+}
+
+mathencodings["tex-mb"] = {
+ -- [0x0] = 0x00, -- lessornotequal \lvertneqq
+ -- [0x0] = 0x01, -- greaterornotequal \gvertneqq
+ [0x02270] = 0x02, -- notlessequal \nleq
+ [0x02271] = 0x03, -- notgreaterequal \ngeq
+ [0x0226E] = 0x04, -- notless \nless
+ [0x0226F] = 0x05, -- notgreater \ngtr
+ [0x02280] = 0x06, -- notprecedes \nprec
+ [0x02281] = 0x07, -- notfollows \nsucc
+ [0x02268] = 0x08, -- lessornotdbleql \lneqq
+ [0x02269] = 0x09, -- greaterornotdbleql \gneqq
+ -- [0x0] = 0x0A, -- notlessorslnteql \nleqslant
+ -- [0x0] = 0x0B, -- notgreaterorslnteql \ngeqslant
+ [0x02A87] = 0x0C, -- lessnotequal \lneq
+ [0x02A88] = 0x0D, -- greaternotequal \gneq
+ -- [0x0] = 0x0E, -- notprecedesoreql \npreceq
+ -- [0x0] = 0x0F, -- notfollowsoreql \nsucceq
+ [0x022E8] = 0x10, -- precedeornoteqvlnt \precnsim
+ [0x022E9] = 0x11, -- followornoteqvlnt \succnsim
+ [0x022E6] = 0x12, -- lessornotsimilar \lnsim
+ [0x022E7] = 0x13, -- greaterornotsimilar \gnsim
+ -- [0x0] = 0x14, -- notlessdblequal \nleqq
+ -- [0x0] = 0x15, -- notgreaterdblequal \ngeqq
+ [0x02AB5] = 0x16, -- precedenotslnteql \precneqq
+ [0x02AB6] = 0x17, -- follownotslnteql \succneqq
+ [0x02AB9] = 0x18, -- precedenotdbleqv \precnapprox
+ [0x02ABA] = 0x19, -- follownotdbleqv \succnapprox
+ [0x02A89] = 0x1A, -- lessnotdblequal \lnapprox
+ [0x02A8A] = 0x1B, -- greaternotdblequal \gnapprox
+ [0x02241] = 0x1C, -- notsimilar \nsim
+ [0x02247] = 0x1D, -- notapproxequal \ncong
+ -- [0x0] = 0x1E, -- upslope \diagup
+ -- [0x0] = 0x1F, -- downslope \diagdown
+ -- [0x0] = 0x20, -- notsubsetoreql \varsubsetneq
+ -- [0x0] = 0x21, -- notsupersetoreql \varsupsetneq
+ -- [0x0] = 0x22, -- notsubsetordbleql \nsubseteqq
+ -- [0x0] = 0x23, -- notsupersetordbleql \nsupseteqq
+ [0x02ACB] = 0x24, -- subsetornotdbleql \subsetneqq
+ [0x02ACC] = 0x25, -- supersetornotdbleql \supsetneqq
+ -- [0x0] = 0x26, -- subsetornoteql \varsubsetneqq
+ -- [0x0] = 0x27, -- supersetornoteql \varsupsetneqq
+ [0x0228A] = 0x28, -- subsetnoteql \subsetneq
+ [0x0228B] = 0x29, -- supersetnoteql \supsetneq
+ [0x02288] = 0x2A, -- notsubseteql \nsubseteq
+ [0x02289] = 0x2B, -- notsuperseteql \nsupseteq
+ [0x02226] = 0x2C, -- notparallel \nparallel
+ [0x02224] = 0x2D, -- notbar \nmid \ndivides
+ -- [0x0] = 0x2E, -- notshortbar \nshortmid
+ -- [0x0] = 0x2F, -- notshortparallel \nshortparallel
+ [0x022AC] = 0x30, -- notturnstile \nvdash
+ [0x022AE] = 0x31, -- notforces \nVdash
+ [0x022AD] = 0x32, -- notsatisfies \nvDash
+ [0x022AF] = 0x33, -- notforcesextra \nVDash
+ [0x022ED] = 0x34, -- nottriangeqlright \ntrianglerighteq
+ [0x022EC] = 0x35, -- nottriangeqlleft \ntrianglelefteq
+ [0x022EA] = 0x36, -- nottriangleleft \ntriangleleft
+ [0x022EB] = 0x37, -- nottriangleright \ntriangleright
+ [0x0219A] = 0x38, -- notarrowleft \nleftarrow
+ [0x0219B] = 0x39, -- notarrowright \nrightarrow
+ [0x021CD] = 0x3A, -- notdblarrowleft \nLeftarrow
+ [0x021CF] = 0x3B, -- notdblarrowright \nRightarrow
+ [0x021CE] = 0x3C, -- notdblarrowboth \nLeftrightarrow
+ [0x021AE] = 0x3D, -- notarrowboth \nleftrightarrow
+ [0x022C7] = 0x3E, -- dividemultiply \divideontimes
+ [0x02300] = 0x3F, -- diametersign \varnothing
+ [0x02204] = 0x40, -- notexistential \nexists
+ [0x1D538] = 0x41, -- A (blackboard A)
+ [0x1D539] = 0x42, -- B
+ [0x02102] = 0x43, -- C
+ [0x1D53B] = 0x44, -- D
+ [0x1D53C] = 0x45, -- E
+ [0x1D53D] = 0x46, -- F
+ [0x1D53E] = 0x47, -- G
+ [0x0210D] = 0x48, -- H
+ [0x1D540] = 0x49, -- I
+ [0x1D541] = 0x4A, -- J
+ [0x1D542] = 0x4B, -- K
+ [0x1D543] = 0x4C, -- L
+ [0x1D544] = 0x4D, -- M
+ [0x02115] = 0x4E, -- N
+ [0x1D546] = 0x4F, -- O
+ [0x02119] = 0x50, -- P
+ [0x0211A] = 0x51, -- Q
+ [0x0211D] = 0x52, -- R
+ [0x1D54A] = 0x53, -- S
+ [0x1D54B] = 0x54, -- T
+ [0x1D54C] = 0x55, -- U
+ [0x1D54D] = 0x56, -- V
+ [0x1D54E] = 0x57, -- W
+ [0x1D54F] = 0x58, -- X
+ [0x1D550] = 0x59, -- Y
+ [0x02124] = 0x5A, -- Z (blackboard Z)
+ [0x02132] = 0x60, -- finv \Finv
+ [0x02141] = 0x61, -- fmir \Game
+ -- [0x0] = 0x62, tildewide
+ -- [0x0] = 0x63, tildewider
+ -- [0x0] = 0x64, Finv
+ -- [0x0] = 0x65, Gmir
+ [0x02127] = 0x66, -- Omegainv \mho
+ [0x000F0] = 0x67, -- eth \eth
+ [0x02242] = 0x68, -- equalorsimilar \eqsim
+ [0x02136] = 0x69, -- beth \beth
+ [0x02137] = 0x6A, -- gimel \gimel
+ [0x02138] = 0x6B, -- daleth \daleth
+ [0x022D6] = 0x6C, -- lessdot \lessdot
+ [0x022D7] = 0x6D, -- greaterdot \gtrdot
+ [0x022C9] = 0x6E, -- multicloseleft \ltimes
+ [0x022CA] = 0x6F, -- multicloseright \rtimes
+ -- [0x0] = 0x70, -- barshort \shortmid
+ -- [0x0] = 0x71, -- parallelshort \shortparallel
+ -- [0x02216] = 0x72, -- integerdivide \smallsetminus (2216 already part of tex-sy
+ -- [0x0] = 0x73, -- similar \thicksim
+ -- [0x0] = 0x74, -- approxequal \thickapprox
+ [0x0224A] = 0x75, -- approxorequal \approxeq
+ [0x02AB8] = 0x76, -- followsorequal \succapprox
+ [0x02AB7] = 0x77, -- precedesorequal \precapprox
+ [0x021B6] = 0x78, -- archleftdown \curvearrowleft
+ [0x021B7] = 0x79, -- archrightdown \curvearrowright
+ [0x003DC] = 0x7A, -- Digamma \digamma
+ [0x003F0] = 0x7B, -- kappa \varkappa
+ [0x1D55C] = 0x7C, -- k \Bbbk (blackboard k)
+ [0x0210F] = 0x7D, -- planckover2pi \hslash
+ [0x00127] = 0x7E, -- planckover2pi1 \hbar
+ [0x003F6] = 0x7F, -- epsiloninv \backepsilon
+}
+
+mathencodings["tex-mc"] = {
+ -- this file has no tfm so it gets mapped in the private space
+ [0xFE324] = "mapsfromchar",
+}
+
+mathencodings["tex-fraktur"] = {
+-- [0x1D504] = 0x41, -- A (fraktur A)
+-- [0x1D505] = 0x42, -- B
+ [0x0212D] = 0x43, -- C
+-- [0x1D507] = 0x44, -- D
+-- [0x1D508] = 0x45, -- E
+-- [0x1D509] = 0x46, -- F
+-- [0x1D50A] = 0x47, -- G
+ [0x0210C] = 0x48, -- H
+ [0x02111] = 0x49, -- I
+-- [0x1D50D] = 0x4A, -- J
+-- [0x1D50E] = 0x4B, -- K
+-- [0x1D50F] = 0x4C, -- L
+-- [0x1D510] = 0x4D, -- M
+-- [0x1D511] = 0x4E, -- N
+-- [0x1D512] = 0x4F, -- O
+-- [0x1D513] = 0x50, -- P
+-- [0x1D514] = 0x51, -- Q
+ [0x0211C] = 0x52, -- R
+-- [0x1D516] = 0x53, -- S
+-- [0x1D517] = 0x54, -- T
+-- [0x1D518] = 0x55, -- U
+-- [0x1D519] = 0x56, -- V
+-- [0x1D51A] = 0x57, -- W
+-- [0x1D51B] = 0x58, -- X
+-- [0x1D51C] = 0x59, -- Y
+ [0x02128] = 0x5A, -- Z (fraktur Z)
+-- [0x1D51E] = 0x61, -- a (fraktur a)
+-- [0x1D51F] = 0x62, -- b
+-- [0x1D520] = 0x63, -- c
+-- [0x1D521] = 0x64, -- d
+-- [0x1D522] = 0x65, -- e
+-- [0x1D523] = 0x66, -- f
+-- [0x1D524] = 0x67, -- g
+-- [0x1D525] = 0x68, -- h
+-- [0x1D526] = 0x69, -- i
+-- [0x1D527] = 0x6A, -- j
+-- [0x1D528] = 0x6B, -- k
+-- [0x1D529] = 0x6C, -- l
+-- [0x1D52A] = 0x6D, -- m
+-- [0x1D52B] = 0x6E, -- n
+-- [0x1D52C] = 0x6F, -- o
+-- [0x1D52D] = 0x70, -- p
+-- [0x1D52E] = 0x71, -- q
+-- [0x1D52F] = 0x72, -- r
+-- [0x1D530] = 0x73, -- s
+-- [0x1D531] = 0x74, -- t
+-- [0x1D532] = 0x75, -- u
+-- [0x1D533] = 0x76, -- v
+-- [0x1D534] = 0x77, -- w
+-- [0x1D535] = 0x78, -- x
+-- [0x1D536] = 0x79, -- y
+-- [0x1D537] = 0x7A, -- z
+}
+
+-- now that all other vectors are defined ...
+
+setletters(mathencodings, "tex-it", 0x1D434, 0x1D44E)
+setletters(mathencodings, "tex-ss", 0x1D5A0, 0x1D5BA)
+setletters(mathencodings, "tex-tt", 0x1D670, 0x1D68A)
+setletters(mathencodings, "tex-bf", 0x1D400, 0x1D41A)
+setletters(mathencodings, "tex-bi", 0x1D468, 0x1D482)
+setletters(mathencodings, "tex-fraktur", 0x1D504, 0x1D51E)
+setletters(mathencodings, "tex-fraktur-bold", 0x1D56C, 0x1D586)
+
+setdigits (mathencodings, "tex-ss", 0x1D7E2)
+setdigits (mathencodings, "tex-tt", 0x1D7F6)
+setdigits (mathencodings, "tex-bf", 0x1D7CE)
+
+-- setdigits (mathencodings, "tex-bi", 0x1D7CE)
+
+-- todo: add ss, tt, bf etc vectors
+-- todo: we can make ss tt etc an option
diff --git a/tex/context/base/math-vfu.lua b/tex/context/base/math-vfu.lua
index 21b101894..b46e06a01 100644
--- a/tex/context/base/math-vfu.lua
+++ b/tex/context/base/math-vfu.lua
@@ -814,299 +814,7 @@ function mathematics.makefont(name,set,goodies)
end
end
--- varphi is part of the alphabet, contrary to the other var*s'
-
-mathencodings["large-to-small"] = {
- [0x00028] = 0x00, -- (
- [0x00029] = 0x01, -- )
- [0x0005B] = 0x02, -- [
- [0x0005D] = 0x03, -- ]
- [0x0230A] = 0x04, -- lfloor
- [0x0230B] = 0x05, -- rfloor
- [0x02308] = 0x06, -- lceil
- [0x02309] = 0x07, -- rceil
- [0x0007B] = 0x08, -- {
- [0x0007D] = 0x09, -- }
- [0x027E8] = 0x0A, -- <
- [0x027E9] = 0x0B, -- >
- [0x0007C] = 0x0C, -- |
---~ [0x0] = 0x0D, -- lVert rVert Vert
--- [0x0002F] = 0x0E, -- /
- [0x0005C] = 0x0F, -- \
---~ [0x0] = 0x3A, -- lgroup
---~ [0x0] = 0x3B, -- rgroup
---~ [0x0] = 0x3C, -- arrowvert
---~ [0x0] = 0x3D, -- Arrowvert
- [0x02195] = 0x3F, -- updownarrow
---~ [0x0] = 0x40, -- lmoustache
---~ [0x0] = 0x41, -- rmoustache
- [0x0221A] = 0x70, -- sqrt
- [0x021D5] = 0x77, -- Updownarrow
- [0x02191] = 0x78, -- uparrow
- [0x02193] = 0x79, -- downarrow
- [0x021D1] = 0x7E, -- Uparrow
- [0x021D3] = 0x7F, -- Downarrow
- [0x0220F] = 0x59, -- prod
- [0x02210] = 0x61, -- coprod
- [0x02211] = 0x58, -- sum
- [0x0222B] = 0x5A, -- intop
- [0x0222E] = 0x49, -- ointop
- [0xFE302] = 0x62, -- widehat
- [0xFE303] = 0x65, -- widetilde
- [0x022C0] = 0x5E, -- bigwedge
- [0x022C1] = 0x5F, -- bigvee
- [0x022C2] = 0x5C, -- bigcap
- [0x022C3] = 0x5B, -- bigcup
- [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
- [0x02210] = 0x60, -- coprod
- [0x02211] = 0x50, -- sum
- [0x0222B] = 0x52, -- intop
- [0x0222E] = 0x48, -- ointop
- [0x022C0] = 0x56, -- bigwedge
- [0x022C1] = 0x57, -- bigvee
- [0x022C2] = 0x54, -- bigcap
- [0x022C3] = 0x53, -- bigcup
- [0x02A00] = 0x4A, -- bigodot -- fixed BJ
- [0x02A01] = 0x4C, -- bigoplus
- [0x02A02] = 0x4E, -- bigotimes
- -- [0x02A03] = , -- bigudot --
- [0x02A04] = 0x55, -- biguplus
- [0x02A06] = 0x46, -- bigsqcup
-}
-
--- only math stuff is needed, since we always use an lm or gyre
--- font as main font
-
-mathencodings["tex-mr"] = {
- [0x00393] = 0x00, -- Gamma
- [0x00394] = 0x01, -- Delta
- [0x00398] = 0x02, -- Theta
- [0x0039B] = 0x03, -- Lambda
- [0x0039E] = 0x04, -- Xi
- [0x003A0] = 0x05, -- Pi
- [0x003A3] = 0x06, -- Sigma
- [0x003A5] = 0x07, -- Upsilon
- [0x003A6] = 0x08, -- Phi
- [0x003A8] = 0x09, -- Psi
- [0x003A9] = 0x0A, -- Omega
--- [0x00060] = 0x12, -- [math]grave
--- [0x000B4] = 0x13, -- [math]acute
--- [0x002C7] = 0x14, -- [math]check
--- [0x002D8] = 0x15, -- [math]breve
--- [0x000AF] = 0x16, -- [math]bar
--- [0x00021] = 0x21, -- !
--- [0x00028] = 0x28, -- (
--- [0x00029] = 0x29, -- )
--- [0x0002B] = 0x2B, -- +
--- [0x0002F] = 0x2F, -- /
--- [0x0003A] = 0x3A, -- :
--- [0x02236] = 0x3A, -- colon
--- [0x0003B] = 0x3B, -- ;
--- [0x0003C] = 0x3C, -- <
--- [0x0003D] = 0x3D, -- =
--- [0x0003E] = 0x3E, -- >
--- [0x0003F] = 0x3F, -- ?
- [0x00391] = 0x41, -- Alpha
- [0x00392] = 0x42, -- Beta
- [0x02145] = 0x44,
- [0x00395] = 0x45, -- Epsilon
- [0x00397] = 0x48, -- Eta
- [0x00399] = 0x49, -- Iota
- [0x0039A] = 0x4B, -- Kappa
- [0x0039C] = 0x4D, -- Mu
- [0x0039D] = 0x4E, -- Nu
- [0x0039F] = 0x4F, -- Omicron
- [0x003A1] = 0x52, -- Rho
- [0x003A4] = 0x54, -- Tau
- [0x003A7] = 0x58, -- Chi
- [0x00396] = 0x5A, -- Zeta
--- [0x0005B] = 0x5B, -- [
--- [0x0005D] = 0x5D, -- ]
--- [0x0005E] = 0x5E, -- [math]hat -- the text one
- [0x00302] = 0x5E, -- [math]hat -- the real math one
--- [0x002D9] = 0x5F, -- [math]dot
- [0x02146] = 0x64,
- [0x02147] = 0x65,
--- [0x002DC] = 0x7E, -- [math]tilde -- the text one
- [0x00303] = 0x7E, -- [math]tilde -- the real one
--- [0x000A8] = 0x7F, -- [math]ddot
-}
-
-mathencodings["tex-mr-missing"] = {
- [0x02236] = 0x3A, -- colon
-}
-
-mathencodings["tex-mi"] = {
- [0x1D6E4] = 0x00, -- Gamma
- [0x1D6E5] = 0x01, -- Delta
- [0x1D6E9] = 0x02, -- Theta
- [0x1D6F3] = 0x02, -- varTheta (not present in TeX)
- [0x1D6EC] = 0x03, -- Lambda
- [0x1D6EF] = 0x04, -- Xi
- [0x1D6F1] = 0x05, -- Pi
- [0x1D6F4] = 0x06, -- Sigma
- [0x1D6F6] = 0x07, -- Upsilon
- [0x1D6F7] = 0x08, -- Phi
- [0x1D6F9] = 0x09, -- Psi
- [0x1D6FA] = 0x0A, -- Omega
- [0x1D6FC] = 0x0B, -- alpha
- [0x1D6FD] = 0x0C, -- beta
- [0x1D6FE] = 0x0D, -- gamma
- [0x1D6FF] = 0x0E, -- delta
- [0x1D716] = 0x0F, -- epsilon TODO: 1D716
- [0x1D701] = 0x10, -- zeta
- [0x1D702] = 0x11, -- eta
- [0x1D703] = 0x12, -- theta TODO: 1D703
- [0x1D704] = 0x13, -- iota
- [0x1D705] = 0x14, -- kappa
- [0x1D718] = 0x14, -- varkappa, not in tex fonts
- [0x1D706] = 0x15, -- lambda
- [0x1D707] = 0x16, -- mu
- [0x1D708] = 0x17, -- nu
- [0x1D709] = 0x18, -- xi
- [0x1D70B] = 0x19, -- pi
- [0x1D70C] = 0x1A, -- rho
- [0x1D70E] = 0x1B, -- sigma
- [0x1D70F] = 0x1C, -- tau
- [0x1D710] = 0x1D, -- upsilon
- [0x1D719] = 0x1E, -- phi
- [0x1D712] = 0x1F, -- chi
- [0x1D713] = 0x20, -- psi
- [0x1D714] = 0x21, -- omega
- [0x1D700] = 0x22, -- varepsilon (the other way around)
- [0x1D717] = 0x23, -- vartheta
- [0x1D71B] = 0x24, -- varpi
- [0x1D71A] = 0x25, -- varrho
- [0x1D70D] = 0x26, -- varsigma
- [0x1D711] = 0x27, -- varphi (the other way around)
- [0x021BC] = 0x28, -- leftharpoonup
- [0x021BD] = 0x29, -- leftharpoondown
- [0x021C0] = 0x2A, -- rightharpoonup
- [0x021C1] = 0x2B, -- rightharpoondown
- [0xFE322] = 0x2C, -- lhook (hook for combining arrows)
- [0xFE323] = 0x2D, -- rhook (hook for combining arrows)
- [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
--- [0x00041] = 0x33, -- 3
--- [0x00041] = 0x34, -- 4
--- [0x00041] = 0x35, -- 5
--- [0x00041] = 0x36, -- 6
--- [0x00041] = 0x37, -- 7
--- [0x00041] = 0x38, -- 8
--- [0x00041] = 0x39, -- 9
---~ [0x0002E] = 0x3A, -- .
- [0x0002C] = 0x3B, -- ,
- [0x0003C] = 0x3C, -- <
--- [0x0002F] = 0x3D, -- /, slash, solidus
- [0x02044] = 0x3D, -- / AM: Not sure
- [0x0003E] = 0x3E, -- >
- [0x022C6] = 0x3F, -- star
- [0x02202] = 0x40, -- partial
---
- [0x0266D] = 0x5B, -- flat
- [0x0266E] = 0x5C, -- natural
- [0x0266F] = 0x5D, -- sharp
- [0x02323] = 0x5E, -- smile
- [0x02322] = 0x5F, -- frown
- [0x02113] = 0x60, -- ell
---
- [0x1D6A4] = 0x7B, -- imath (TODO: also 0131)
- [0x1D6A5] = 0x7C, -- jmath (TODO: also 0237)
- [0x02118] = 0x7D, -- wp
- [0x020D7] = 0x7E, -- vec (TODO: not sure)
--- 0x7F, -- (no idea what that could be)
-}
-
-mathencodings["tex-it"] = {
--- [0x1D434] = 0x41, -- A
- [0x1D6E2] = 0x41, -- Alpha
--- [0x1D435] = 0x42, -- B
- [0x1D6E3] = 0x42, -- Beta
--- [0x1D436] = 0x43, -- C
--- [0x1D437] = 0x44, -- D
--- [0x1D438] = 0x45, -- E
- [0x1D6E6] = 0x45, -- Epsilon
--- [0x1D439] = 0x46, -- F
--- [0x1D43A] = 0x47, -- G
--- [0x1D43B] = 0x48, -- H
- [0x1D6E8] = 0x48, -- Eta
--- [0x1D43C] = 0x49, -- I
- [0x1D6EA] = 0x49, -- Iota
--- [0x1D43D] = 0x4A, -- J
--- [0x1D43E] = 0x4B, -- K
- [0x1D6EB] = 0x4B, -- Kappa
--- [0x1D43F] = 0x4C, -- L
--- [0x1D440] = 0x4D, -- M
- [0x1D6ED] = 0x4D, -- Mu
--- [0x1D441] = 0x4E, -- N
- [0x1D6EE] = 0x4E, -- Nu
--- [0x1D442] = 0x4F, -- O
- [0x1D6F0] = 0x4F, -- Omicron
--- [0x1D443] = 0x50, -- P
- [0x1D6F2] = 0x50, -- Rho
--- [0x1D444] = 0x51, -- Q
--- [0x1D445] = 0x52, -- R
--- [0x1D446] = 0x53, -- S
--- [0x1D447] = 0x54, -- T
- [0x1D6F5] = 0x54, -- Tau
--- [0x1D448] = 0x55, -- U
--- [0x1D449] = 0x56, -- V
--- [0x1D44A] = 0x57, -- W
--- [0x1D44B] = 0x58, -- X
- [0x1D6F8] = 0x58, -- Chi
--- [0x1D44C] = 0x59, -- Y
--- [0x1D44D] = 0x5A, -- Z
---
--- [0x1D44E] = 0x61, -- a
--- [0x1D44F] = 0x62, -- b
--- [0x1D450] = 0x63, -- c
--- [0x1D451] = 0x64, -- d
--- [0x1D452] = 0x65, -- e
--- [0x1D453] = 0x66, -- f
--- [0x1D454] = 0x67, -- g
--- [0x1D455] = 0x68, -- h
- [0x0210E] = 0x68, -- Planck constant (h)
--- [0x1D456] = 0x69, -- i
--- [0x1D457] = 0x6A, -- j
--- [0x1D458] = 0x6B, -- k
--- [0x1D459] = 0x6C, -- l
--- [0x1D45A] = 0x6D, -- m
--- [0x1D45B] = 0x6E, -- n
--- [0x1D45C] = 0x6F, -- o
- [0x1D70A] = 0x6F, -- omicron
--- [0x1D45D] = 0x70, -- p
--- [0x1D45E] = 0x71, -- q
--- [0x1D45F] = 0x72, -- r
--- [0x1D460] = 0x73, -- s
--- [0x1D461] = 0x74, -- t
--- [0x1D462] = 0x75, -- u
--- [0x1D463] = 0x76, -- v
--- [0x1D464] = 0x77, -- w
--- [0x1D465] = 0x78, -- x
--- [0x1D466] = 0x79, -- y
--- [0x1D467] = 0x7A, -- z
-}
-
-mathencodings["tex-ss"] = { }
-mathencodings["tex-tt"] = { }
-mathencodings["tex-bf"] = { }
-mathencodings["tex-bi"] = { }
-mathencodings["tex-fraktur"] = { }
-mathencodings["tex-fraktur-bold"] = { }
+-- helpers
function vfmath.setletters(font_encoding, name, uppercase, lowercase)
local enc = font_encoding[name]
@@ -1122,494 +830,3 @@ function vfmath.setdigits(font_encoding, name, digits)
enc[digits+i] = i + 0x30
end
end
-
-mathencodings["tex-sy"] = {
- [0x0002D] = 0x00, -- -
- [0x02212] = 0x00, -- -
--- [0x02201] = 0x00, -- complement
--- [0x02206] = 0x00, -- increment
--- [0x02204] = 0x00, -- not exists
--- [0x000B7] = 0x01, -- cdot
- [0x022C5] = 0x01, -- cdot
- [0x000D7] = 0x02, -- times
- [0x0002A] = 0x03, -- *
- [0x02217] = 0x03, -- *
- [0x000F7] = 0x04, -- div
- [0x022C4] = 0x05, -- diamond
- [0x000B1] = 0x06, -- pm
- [0x02213] = 0x07, -- mp
- [0x02295] = 0x08, -- oplus
- [0x02296] = 0x09, -- ominus
- [0x02297] = 0x0A, -- otimes
- [0x02298] = 0x0B, -- oslash
- [0x02299] = 0x0C, -- odot
- [0x025EF] = 0x0D, -- bigcirc, Orb (either 25EF or 25CB) -- todo
- [0x02218] = 0x0E, -- circ
- [0x02219] = 0x0F, -- bullet
- [0x02022] = 0x0F, -- bullet
- [0x0224D] = 0x10, -- asymp
- [0x02261] = 0x11, -- equiv
- [0x02286] = 0x12, -- subseteq
- [0x02287] = 0x13, -- supseteq
- [0x02264] = 0x14, -- leq
- [0x02265] = 0x15, -- geq
- [0x02AAF] = 0x16, -- preceq
--- [0x0227C] = 0x16, -- preceq, AM:No see 2AAF
- [0x02AB0] = 0x17, -- succeq
--- [0x0227D] = 0x17, -- succeq, AM:No see 2AB0
- [0x0223C] = 0x18, -- sim
- [0x02248] = 0x19, -- approx
- [0x02282] = 0x1A, -- subset
- [0x02283] = 0x1B, -- supset
- [0x0226A] = 0x1C, -- ll
- [0x0226B] = 0x1D, -- gg
- [0x0227A] = 0x1E, -- prec
- [0x0227B] = 0x1F, -- succ
- [0x02190] = 0x20, -- leftarrow
- [0x02192] = 0x21, -- rightarrow
---~ [0xFE190] = 0x20, -- leftarrow
---~ [0xFE192] = 0x21, -- rightarrow
- [0x02191] = 0x22, -- uparrow
- [0x02193] = 0x23, -- downarrow
- [0x02194] = 0x24, -- leftrightarrow
- [0x02197] = 0x25, -- nearrow
- [0x02198] = 0x26, -- searrow
- [0x02243] = 0x27, -- simeq
- [0x021D0] = 0x28, -- Leftarrow
- [0x021D2] = 0x29, -- Rightarrow
- [0x021D1] = 0x2A, -- Uparrow
- [0x021D3] = 0x2B, -- Downarrow
- [0x021D4] = 0x2C, -- Leftrightarrow
- [0x02196] = 0x2D, -- nwarrow
- [0x02199] = 0x2E, -- swarrow
- [0x0221D] = 0x2F, -- propto
- [0x02032] = 0x30, -- prime
- [0x0221E] = 0x31, -- infty
- [0x02208] = 0x32, -- in
- [0x0220B] = 0x33, -- ni
- [0x025B3] = 0x34, -- triangle, bigtriangleup
- [0x025BD] = 0x35, -- bigtriangledown
- [0x00338] = 0x36, -- not
--- 0x37, -- (beginning of arrow)
- [0x02200] = 0x38, -- forall
- [0x02203] = 0x39, -- exists
- [0x000AC] = 0x3A, -- neg, lnot
- [0x02205] = 0x3B, -- empty set
- [0x0211C] = 0x3C, -- Re
- [0x02111] = 0x3D, -- Im
- [0x022A4] = 0x3E, -- top
- [0x022A5] = 0x3F, -- bot, perp
- [0x02135] = 0x40, -- aleph
- [0x1D49C] = 0x41, -- script A
- [0x0212C] = 0x42, -- script B
- [0x1D49E] = 0x43, -- script C
- [0x1D49F] = 0x44, -- script D
- [0x02130] = 0x45, -- script E
- [0x02131] = 0x46, -- script F
- [0x1D4A2] = 0x47, -- script G
- [0x0210B] = 0x48, -- script H
- [0x02110] = 0x49, -- script I
- [0x1D4A5] = 0x4A, -- script J
- [0x1D4A6] = 0x4B, -- script K
- [0x02112] = 0x4C, -- script L
- [0x02133] = 0x4D, -- script M
- [0x1D4A9] = 0x4E, -- script N
- [0x1D4AA] = 0x4F, -- script O
- [0x1D4AB] = 0x50, -- script P
- [0x1D4AC] = 0x51, -- script Q
- [0x0211B] = 0x52, -- script R
- [0x1D4AE] = 0x53, -- script S
- [0x1D4AF] = 0x54, -- script T
- [0x1D4B0] = 0x55, -- script U
- [0x1D4B1] = 0x56, -- script V
- [0x1D4B2] = 0x57, -- script W
- [0x1D4B3] = 0x58, -- script X
- [0x1D4B4] = 0x59, -- script Y
- [0x1D4B5] = 0x5A, -- script Z
- [0x0222A] = 0x5B, -- cup
- [0x02229] = 0x5C, -- cap
- [0x0228E] = 0x5D, -- uplus
- [0x02227] = 0x5E, -- wedge, land
- [0x02228] = 0x5F, -- vee, lor
- [0x022A2] = 0x60, -- vdash
- [0x022A3] = 0x61, -- dashv
- [0x0230A] = 0x62, -- lfloor
- [0x0230B] = 0x63, -- rfloor
- [0x02308] = 0x64, -- lceil
- [0x02309] = 0x65, -- rceil
- [0x0007B] = 0x66, -- {, lbrace
- [0x0007D] = 0x67, -- }, rbrace
- [0x027E8] = 0x68, -- <, langle
- [0x027E9] = 0x69, -- >, rangle
- [0x0007C] = 0x6A, -- |, mid, lvert, rvert
- [0x02225] = 0x6B, -- parallel
- -- [0x02016] = 0x00, -- Vert, lVert, rVert, arrowvert, Arrowvert
- [0x02195] = 0x6C, -- updownarrow
- [0x021D5] = 0x6D, -- Updownarrow
- [0x0005C] = 0x6E, -- \, backslash, setminus
- [0x02216] = 0x6E, -- setminus
- [0x02240] = 0x6F, -- wr
- [0x0221A] = 0x70, -- sqrt. AM: Check surd??
- [0x02A3F] = 0x71, -- amalg
- [0x1D6FB] = 0x72, -- nabla
--- [0x0222B] = 0x73, -- smallint (TODO: what about intop?)
- [0x02294] = 0x74, -- sqcup
- [0x02293] = 0x75, -- sqcap
- [0x02291] = 0x76, -- sqsubseteq
- [0x02292] = 0x77, -- sqsupseteq
- [0x000A7] = 0x78, -- S
- [0x02020] = 0x79, -- dagger, dag
- [0x02021] = 0x7A, -- ddagger, ddag
- [0x000B6] = 0x7B, -- P
- [0x02663] = 0x7C, -- clubsuit
- [0x02662] = 0x7D, -- diamondsuit
- [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
--- column, while in the second column we show the tex/ams names. As usual
--- it costs hours to figure out such a table.
-
-mathencodings["tex-ma"] = {
- [0x022A1] = 0x00, -- squaredot \boxdot
- [0x0229E] = 0x01, -- squareplus \boxplus
- [0x022A0] = 0x02, -- squaremultiply \boxtimes
- [0x025A1] = 0x03, -- square \square \Box
- [0x025A0] = 0x04, -- squaresolid \blacksquare
- [0x025AA] = 0x05, -- squaresmallsolid \centerdot
- [0x022C4] = 0x06, -- diamond \Diamond \lozenge
- [0x02666] = 0x07, -- diamondsolid \blacklozenge
- [0x021BB] = 0x08, -- clockwise \circlearrowright
- [0x021BA] = 0x09, -- anticlockwise \circlearrowleft
- [0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons
- [0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons
- [0x0229F] = 0x0C, -- squareminus \boxminus
- [0x022A9] = 0x0D, -- forces \Vdash
- [0x022AA] = 0x0E, -- forcesbar \Vvdash
- [0x022A8] = 0x0F, -- satisfies \vDash
- [0x021A0] = 0x10, -- dblarrowheadright \twoheadrightarrow
- [0x0219E] = 0x11, -- dblarrowheadleft \twoheadleftarrow
- [0x021C7] = 0x12, -- dblarrowleft \leftleftarrows
- [0x021C9] = 0x13, -- dblarrowright \rightrightarrows
- [0x021C8] = 0x14, -- dblarrowup \upuparrows
- [0x021CA] = 0x15, -- dblarrowdwn \downdownarrows
- [0x021BE] = 0x16, -- harpoonupright \upharpoonright \restriction
- [0x021C2] = 0x17, -- harpoondownright \downharpoonright
- [0x021BF] = 0x18, -- harpoonupleft \upharpoonleft
- [0x021C3] = 0x19, -- harpoondownleft \downharpoonleft
- [0x021A3] = 0x1A, -- arrowtailright \rightarrowtail
- [0x021A2] = 0x1B, -- arrowtailleft \leftarrowtail
- [0x021C6] = 0x1C, -- arrowparrleftright \leftrightarrows
--- [0x021C5] = 0x00, -- \updownarrows (missing in lm)
- [0x021C4] = 0x1D, -- arrowparrrightleft \rightleftarrows
- [0x021B0] = 0x1E, -- shiftleft \Lsh
- [0x021B1] = 0x1F, -- shiftright \Rsh
- [0x021DD] = 0x20, -- squiggleright \leadsto \rightsquigarrow
- [0x021AD] = 0x21, -- squiggleleftright \leftrightsquigarrow
- [0x021AB] = 0x22, -- curlyleft \looparrowleft
- [0x021AC] = 0x23, -- curlyright \looparrowright
- [0x02257] = 0x24, -- circleequal \circeq
- [0x0227F] = 0x25, -- followsorequal \succsim
- [0x02273] = 0x26, -- greaterorsimilar \gtrsim
- [0x02A86] = 0x27, -- greaterorapproxeql \gtrapprox
- [0x022B8] = 0x28, -- multimap \multimap
- [0x02234] = 0x29, -- therefore \therefore
- [0x02235] = 0x2A, -- because \because
- [0x02251] = 0x2B, -- equalsdots \Doteq \doteqdot
- [0x0225C] = 0x2C, -- defines \triangleq
- [0x0227E] = 0x2D, -- precedesorequal \precsim
- [0x02272] = 0x2E, -- lessorsimilar \lesssim
- [0x02A85] = 0x2F, -- lessorapproxeql \lessapprox
- [0x02A95] = 0x30, -- equalorless \eqslantless
- [0x02A96] = 0x31, -- equalorgreater \eqslantgtr
- [0x022DE] = 0x32, -- equalorprecedes \curlyeqprec
- [0x022DF] = 0x33, -- equalorfollows \curlyeqsucc
- [0x0227C] = 0x34, -- precedesorcurly \preccurlyeq
- [0x02266] = 0x35, -- lessdblequal \leqq
- [0x02A7D] = 0x36, -- lessorequalslant \leqslant
- [0x02276] = 0x37, -- lessorgreater \lessgtr
- [0x02035] = 0x38, -- primereverse \backprime
- -- [0x0] = 0x39, -- axisshort \dabar
- [0x02253] = 0x3A, -- equaldotrightleft \risingdotseq
- [0x02252] = 0x3B, -- equaldotleftright \fallingdotseq
- [0x0227D] = 0x3C, -- followsorcurly \succcurlyeq
- [0x02267] = 0x3D, -- greaterdblequal \geqq
- [0x02A7E] = 0x3E, -- greaterorequalslant \geqslant
- [0x02277] = 0x3F, -- greaterorless \gtrless
- [0x0228F] = 0x40, -- squareimage \sqsubset
- [0x02290] = 0x41, -- squareoriginal \sqsupset
- -- wrong: see **
- -- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright
- -- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft
- -- cf lm
- [0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq
- [0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq
- --
- [0x02605] = 0x46, -- star \bigstar
- [0x0226C] = 0x47, -- between \between
- [0x025BC] = 0x48, -- triangledownsld \blacktriangledown
- [0x025B6] = 0x49, -- trianglerightsld \blacktriangleright
- [0x025C0] = 0x4A, -- triangleleftsld \blacktriangleleft
- -- [0x0] = 0x4B, -- arrowaxisright
- -- [0x0] = 0x4C, -- arrowaxisleft
- [0x025B2] = 0x4D, -- triangle \triangleup \vartriangle
- [0x025B2] = 0x4E, -- trianglesolid \blacktriangle
- [0x025BC] = 0x4F, -- triangleinv \triangledown
- [0x02256] = 0x50, -- ringinequal \eqcirc
- [0x022DA] = 0x51, -- lessequalgreater \lesseqgtr
- [0x022DB] = 0x52, -- greaterlessequal \gtreqless
- [0x02A8B] = 0x53, -- lessdbleqlgreater \lesseqqgtr
- [0x02A8C] = 0x54, -- greaterdbleqlless \gtreqqless
- [0x000A5] = 0x55, -- Yen \yen
- [0x021DB] = 0x56, -- arrowtripleright \Rrightarrow
- [0x021DA] = 0x57, -- arrowtripleleft \Lleftarrow
- [0x02713] = 0x58, -- check \checkmark
- [0x022BB] = 0x59, -- orunderscore \veebar
- [0x022BC] = 0x5A, -- nand \barwedge
- [0x02306] = 0x5B, -- perpcorrespond \doublebarwedge
- [0x02220] = 0x5C, -- angle \angle
- [0x02221] = 0x5D, -- measuredangle \measuredangle
- [0x02222] = 0x5E, -- sphericalangle \sphericalangle
- -- [0x0] = 0x5F, -- proportional \varpropto
- -- [0x0] = 0x60, -- smile \smallsmile
- -- [0x0] = 0x61, -- frown \smallfrown
- [0x022D0] = 0x62, -- subsetdbl \Subset
- [0x022D1] = 0x63, -- supersetdbl \Supset
- [0x022D3] = 0x64, -- uniondbl \doublecup \Cup
- [0x022D2] = 0x65, -- intersectiondbl \doublecap \Cap
- [0x022CF] = 0x66, -- uprise \curlywedge
- [0x022CE] = 0x67, -- downfall \curlyvee
- [0x022CB] = 0x68, -- multiopenleft \leftthreetimes
- [0x022CC] = 0x69, -- multiopenright \rightthreetimes
- [0x02AC5] = 0x6A, -- subsetdblequal \subseteqq
- [0x02AC6] = 0x6B, -- supersetdblequal \supseteqq
- [0x0224F] = 0x6C, -- difference \bumpeq
- [0x0224E] = 0x6D, -- geomequivalent \Bumpeq
- [0x022D8] = 0x6E, -- muchless \lll \llless
- [0x022D9] = 0x6F, -- muchgreater \ggg \gggtr
- [0x0231C] = 0x70, -- rightanglenw \ulcorner
- [0x0231D] = 0x71, -- rightanglene \urcorner
- [0x024C7] = 0x72, -- circleR \circledR
- [0x024C8] = 0x73, -- circleS \circledS
- [0x022D4] = 0x74, -- fork \pitchfork
- [0x02214] = 0x75, -- dotplus \dotplus
- [0x0223D] = 0x76, -- revsimilar \backsim
- [0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq.
- [0x0231E] = 0x78, -- rightanglesw \llcorner
- [0x0231F] = 0x79, -- rightanglese \lrcorner
- [0x02720] = 0x7A, -- maltesecross \maltese
- [0x02201] = 0x7B, -- complement \complement
- [0x022BA] = 0x7C, -- intercal \intercal
- [0x0229A] = 0x7D, -- circlering \circledcirc
- [0x0229B] = 0x7E, -- circleasterisk \circledast
- [0x0229D] = 0x7F, -- circleminus \circleddash
-}
-
-mathencodings["tex-mb"] = {
- -- [0x0] = 0x00, -- lessornotequal \lvertneqq
- -- [0x0] = 0x01, -- greaterornotequal \gvertneqq
- [0x02270] = 0x02, -- notlessequal \nleq
- [0x02271] = 0x03, -- notgreaterequal \ngeq
- [0x0226E] = 0x04, -- notless \nless
- [0x0226F] = 0x05, -- notgreater \ngtr
- [0x02280] = 0x06, -- notprecedes \nprec
- [0x02281] = 0x07, -- notfollows \nsucc
- [0x02268] = 0x08, -- lessornotdbleql \lneqq
- [0x02269] = 0x09, -- greaterornotdbleql \gneqq
- -- [0x0] = 0x0A, -- notlessorslnteql \nleqslant
- -- [0x0] = 0x0B, -- notgreaterorslnteql \ngeqslant
- [0x02A87] = 0x0C, -- lessnotequal \lneq
- [0x02A88] = 0x0D, -- greaternotequal \gneq
- -- [0x0] = 0x0E, -- notprecedesoreql \npreceq
- -- [0x0] = 0x0F, -- notfollowsoreql \nsucceq
- [0x022E8] = 0x10, -- precedeornoteqvlnt \precnsim
- [0x022E9] = 0x11, -- followornoteqvlnt \succnsim
- [0x022E6] = 0x12, -- lessornotsimilar \lnsim
- [0x022E7] = 0x13, -- greaterornotsimilar \gnsim
- -- [0x0] = 0x14, -- notlessdblequal \nleqq
- -- [0x0] = 0x15, -- notgreaterdblequal \ngeqq
- [0x02AB5] = 0x16, -- precedenotslnteql \precneqq
- [0x02AB6] = 0x17, -- follownotslnteql \succneqq
- [0x02AB9] = 0x18, -- precedenotdbleqv \precnapprox
- [0x02ABA] = 0x19, -- follownotdbleqv \succnapprox
- [0x02A89] = 0x1A, -- lessnotdblequal \lnapprox
- [0x02A8A] = 0x1B, -- greaternotdblequal \gnapprox
- [0x02241] = 0x1C, -- notsimilar \nsim
- [0x02247] = 0x1D, -- notapproxequal \ncong
- -- [0x0] = 0x1E, -- upslope \diagup
- -- [0x0] = 0x1F, -- downslope \diagdown
- -- [0x0] = 0x20, -- notsubsetoreql \varsubsetneq
- -- [0x0] = 0x21, -- notsupersetoreql \varsupsetneq
- -- [0x0] = 0x22, -- notsubsetordbleql \nsubseteqq
- -- [0x0] = 0x23, -- notsupersetordbleql \nsupseteqq
- [0x02ACB] = 0x24, -- subsetornotdbleql \subsetneqq
- [0x02ACC] = 0x25, -- supersetornotdbleql \supsetneqq
- -- [0x0] = 0x26, -- subsetornoteql \varsubsetneqq
- -- [0x0] = 0x27, -- supersetornoteql \varsupsetneqq
- [0x0228A] = 0x28, -- subsetnoteql \subsetneq
- [0x0228B] = 0x29, -- supersetnoteql \supsetneq
- [0x02288] = 0x2A, -- notsubseteql \nsubseteq
- [0x02289] = 0x2B, -- notsuperseteql \nsupseteq
- [0x02226] = 0x2C, -- notparallel \nparallel
- [0x02224] = 0x2D, -- notbar \nmid \ndivides
- -- [0x0] = 0x2E, -- notshortbar \nshortmid
- -- [0x0] = 0x2F, -- notshortparallel \nshortparallel
- [0x022AC] = 0x30, -- notturnstile \nvdash
- [0x022AE] = 0x31, -- notforces \nVdash
- [0x022AD] = 0x32, -- notsatisfies \nvDash
- [0x022AF] = 0x33, -- notforcesextra \nVDash
- [0x022ED] = 0x34, -- nottriangeqlright \ntrianglerighteq
- [0x022EC] = 0x35, -- nottriangeqlleft \ntrianglelefteq
- [0x022EA] = 0x36, -- nottriangleleft \ntriangleleft
- [0x022EB] = 0x37, -- nottriangleright \ntriangleright
- [0x0219A] = 0x38, -- notarrowleft \nleftarrow
- [0x0219B] = 0x39, -- notarrowright \nrightarrow
- [0x021CD] = 0x3A, -- notdblarrowleft \nLeftarrow
- [0x021CF] = 0x3B, -- notdblarrowright \nRightarrow
- [0x021CE] = 0x3C, -- notdblarrowboth \nLeftrightarrow
- [0x021AE] = 0x3D, -- notarrowboth \nleftrightarrow
- [0x022C7] = 0x3E, -- dividemultiply \divideontimes
- [0x02300] = 0x3F, -- diametersign \varnothing
- [0x02204] = 0x40, -- notexistential \nexists
- [0x1D538] = 0x41, -- A (blackboard A)
- [0x1D539] = 0x42, -- B
- [0x02102] = 0x43, -- C
- [0x1D53B] = 0x44, -- D
- [0x1D53C] = 0x45, -- E
- [0x1D53D] = 0x46, -- F
- [0x1D53E] = 0x47, -- G
- [0x0210D] = 0x48, -- H
- [0x1D540] = 0x49, -- I
- [0x1D541] = 0x4A, -- J
- [0x1D542] = 0x4B, -- K
- [0x1D543] = 0x4C, -- L
- [0x1D544] = 0x4D, -- M
- [0x02115] = 0x4E, -- N
- [0x1D546] = 0x4F, -- O
- [0x02119] = 0x50, -- P
- [0x0211A] = 0x51, -- Q
- [0x0211D] = 0x52, -- R
- [0x1D54A] = 0x53, -- S
- [0x1D54B] = 0x54, -- T
- [0x1D54C] = 0x55, -- U
- [0x1D54D] = 0x56, -- V
- [0x1D54E] = 0x57, -- W
- [0x1D54F] = 0x58, -- X
- [0x1D550] = 0x59, -- Y
- [0x02124] = 0x5A, -- Z (blackboard Z)
- [0x02132] = 0x60, -- finv \Finv
- [0x02141] = 0x61, -- fmir \Game
- -- [0x0] = 0x62, tildewide
- -- [0x0] = 0x63, tildewider
- -- [0x0] = 0x64, Finv
- -- [0x0] = 0x65, Gmir
- [0x02127] = 0x66, -- Omegainv \mho
- [0x000F0] = 0x67, -- eth \eth
- [0x02242] = 0x68, -- equalorsimilar \eqsim
- [0x02136] = 0x69, -- beth \beth
- [0x02137] = 0x6A, -- gimel \gimel
- [0x02138] = 0x6B, -- daleth \daleth
- [0x022D6] = 0x6C, -- lessdot \lessdot
- [0x022D7] = 0x6D, -- greaterdot \gtrdot
- [0x022C9] = 0x6E, -- multicloseleft \ltimes
- [0x022CA] = 0x6F, -- multicloseright \rtimes
- -- [0x0] = 0x70, -- barshort \shortmid
- -- [0x0] = 0x71, -- parallelshort \shortparallel
- -- [0x02216] = 0x72, -- integerdivide \smallsetminus (2216 already part of tex-sy
- -- [0x0] = 0x73, -- similar \thicksim
- -- [0x0] = 0x74, -- approxequal \thickapprox
- [0x0224A] = 0x75, -- approxorequal \approxeq
- [0x02AB8] = 0x76, -- followsorequal \succapprox
- [0x02AB7] = 0x77, -- precedesorequal \precapprox
- [0x021B6] = 0x78, -- archleftdown \curvearrowleft
- [0x021B7] = 0x79, -- archrightdown \curvearrowright
- [0x003DC] = 0x7A, -- Digamma \digamma
- [0x003F0] = 0x7B, -- kappa \varkappa
- [0x1D55C] = 0x7C, -- k \Bbbk (blackboard k)
- [0x0210F] = 0x7D, -- planckover2pi \hslash
- [0x00127] = 0x7E, -- planckover2pi1 \hbar
- [0x003F6] = 0x7F, -- epsiloninv \backepsilon
-}
-
-mathencodings["tex-mc"] = {
- -- this file has no tfm so it gets mapped in the private space
- [0xFE324] = "mapsfromchar",
-}
-
-mathencodings["tex-fraktur"] = {
--- [0x1D504] = 0x41, -- A (fraktur A)
--- [0x1D505] = 0x42, -- B
- [0x0212D] = 0x43, -- C
--- [0x1D507] = 0x44, -- D
--- [0x1D508] = 0x45, -- E
--- [0x1D509] = 0x46, -- F
--- [0x1D50A] = 0x47, -- G
- [0x0210C] = 0x48, -- H
- [0x02111] = 0x49, -- I
--- [0x1D50D] = 0x4A, -- J
--- [0x1D50E] = 0x4B, -- K
--- [0x1D50F] = 0x4C, -- L
--- [0x1D510] = 0x4D, -- M
--- [0x1D511] = 0x4E, -- N
--- [0x1D512] = 0x4F, -- O
--- [0x1D513] = 0x50, -- P
--- [0x1D514] = 0x51, -- Q
- [0x0211C] = 0x52, -- R
--- [0x1D516] = 0x53, -- S
--- [0x1D517] = 0x54, -- T
--- [0x1D518] = 0x55, -- U
--- [0x1D519] = 0x56, -- V
--- [0x1D51A] = 0x57, -- W
--- [0x1D51B] = 0x58, -- X
--- [0x1D51C] = 0x59, -- Y
- [0x02128] = 0x5A, -- Z (fraktur Z)
--- [0x1D51E] = 0x61, -- a (fraktur a)
--- [0x1D51F] = 0x62, -- b
--- [0x1D520] = 0x63, -- c
--- [0x1D521] = 0x64, -- d
--- [0x1D522] = 0x65, -- e
--- [0x1D523] = 0x66, -- f
--- [0x1D524] = 0x67, -- g
--- [0x1D525] = 0x68, -- h
--- [0x1D526] = 0x69, -- i
--- [0x1D527] = 0x6A, -- j
--- [0x1D528] = 0x6B, -- k
--- [0x1D529] = 0x6C, -- l
--- [0x1D52A] = 0x6D, -- m
--- [0x1D52B] = 0x6E, -- n
--- [0x1D52C] = 0x6F, -- o
--- [0x1D52D] = 0x70, -- p
--- [0x1D52E] = 0x71, -- q
--- [0x1D52F] = 0x72, -- r
--- [0x1D530] = 0x73, -- s
--- [0x1D531] = 0x74, -- t
--- [0x1D532] = 0x75, -- u
--- [0x1D533] = 0x76, -- v
--- [0x1D534] = 0x77, -- w
--- [0x1D535] = 0x78, -- x
--- [0x1D536] = 0x79, -- y
--- [0x1D537] = 0x7A, -- z
-}
-
--- now that all other vectors are defined ...
-
-vfmath.setletters(mathencodings, "tex-it", 0x1D434, 0x1D44E)
-vfmath.setletters(mathencodings, "tex-ss", 0x1D5A0, 0x1D5BA)
-vfmath.setletters(mathencodings, "tex-tt", 0x1D670, 0x1D68A)
-vfmath.setletters(mathencodings, "tex-bf", 0x1D400, 0x1D41A)
-vfmath.setletters(mathencodings, "tex-bi", 0x1D468, 0x1D482)
-vfmath.setletters(mathencodings, "tex-fraktur", 0x1D504, 0x1D51E)
-vfmath.setletters(mathencodings, "tex-fraktur-bold", 0x1D56C, 0x1D586)
-
-vfmath.setdigits (mathencodings, "tex-ss", 0x1D7E2)
-vfmath.setdigits (mathencodings, "tex-tt", 0x1D7F6)
-vfmath.setdigits (mathencodings, "tex-bf", 0x1D7CE)
-
--- vfmath.setdigits (mathencodings, "tex-bi", 0x1D7CE)
-
--- todo: add ss, tt, bf etc vectors
--- todo: we can make ss tt etc an option
diff --git a/tex/context/base/meta-grd.mkiv b/tex/context/base/meta-grd.mkiv
new file mode 100644
index 000000000..da410ba68
--- /dev/null
+++ b/tex/context/base/meta-grd.mkiv
@@ -0,0 +1,116 @@
+%D \module
+%D [ file=meta-grd,
+%D version=2012.06.28,
+%D title=\METAPOST\ Graphics,
+%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}{MetaPost Graphics / Grids}
+
+%D This used to be a \TEX\ method, and a rather old one too. We keep it around but
+%D in a more modern way.
+%D
+%D \startbuffer
+%D \basegrid
+%D [nx=8,ny=5,
+%D dx=.5,dy=.25,
+%D unit=cm,scale=2,factor=1,
+%D offset=1ex,xstep=2,ystep=1,
+%D align=middle,style=\tt\tx]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \placefigure
+%D {An example of a grid.}
+%D {\getbuffer}
+
+\startuseMPgraphic{grid}{nx,ny,dx,dy,factor,scale,xstep,ystep,xoffset,yoffset,align}
+ begingroup ;
+
+ save nx, ny, dx, dy, wd, ht, xstep, ystep, xoffset, yoffset, align, xalign, yalign ;
+
+ numeric nx ; nx := \MPvar{nx} ;
+ numeric ny ; ny := \MPvar{ny} ;
+ numeric dx ; dx := \MPvar{factor} * \MPvar{scale} * \MPvar{dx} ;
+ numeric dy ; dy := \MPvar{factor} * \MPvar{scale} * \MPvar{dy} ;
+ numeric wd ; wd := nx * dx ;
+ numeric ht ; ht := ny * dy ;
+ numeric xstep ; xstep := \MPvar{xstep} ;
+ numeric ystep ; ystep := \MPvar{ystep} ;
+ numeric xoffset ; xoffset := \MPvar{xoffset} ;
+ numeric yoffset ; yoffset := \MPvar{yoffset} ;
+ numeric align ; align := \MPvar{align} ;
+ numeric xalign ; xalign := 0 ;
+ numeric yalign ; yalign := 0 ;
+
+ if align = 1 :
+ xalign := dx/2 ;
+ yalign := dy/2 ;
+ fi ;
+
+ for i=0 step dx until wd :
+ draw (i,0) -- (i,ht) ;
+ endfor ;
+ for i=0 step dy until ht :
+ draw (0,i) -- (wd,i) ;
+ endfor ;
+
+ if xstep > 0 :
+ for i=1 step xstep until nx :
+ draw thetextext.bot(decimal i,(i*dx-xalign,-xoffset)) ;
+ endfor ;
+ fi ;
+ if ystep > 0 :
+ for i=1 step ystep until ny :
+ draw thetextext.lft(decimal i,(-yoffset,i*dy-yalign)) ;
+ endfor ;
+ fi ;
+
+ endgroup ;
+\stopuseMPgraphic
+
+\unprotect
+
+\unexpanded\def\basegrid
+ {\dosingleempty\typo_grid_base}
+
+\def\typo_grid_base[#1]%
+ {\hbox\bgroup
+ \getdummyparameters
+ [\c!nx=10,\c!ny=10,\c!dx=.5,\c!dy=.5,\c!xstep=0,\c!ystep=0,
+ \c!unit=\s!cm,\c!scale=1,\c!factor=1,
+ \c!offset=.25ex,\c!xoffset=\directdummyparameter\c!offset,\c!yoffset=\directdummyparameter\c!offset,
+ \c!align=,
+ #1]%
+ \usedummystyleandcolor\c!style\c!color
+ \edef\p_align{\directdummyparameter\c!align}%
+ \ifx\p_align\v!middle
+ \let\p_align\!!plusone
+ \else
+ \let\p_align\!!zerocount
+ \fi
+ \useMPgraphic
+ {grid}%
+ {nx=\directdummyparameter\c!nx,%
+ ny=\directdummyparameter\c!ny,%
+ dx=\directdummyparameter\c!dx\directdummyparameter\c!unit,%
+ dy=\directdummyparameter\c!dy\directdummyparameter\c!unit,%
+ factor=\directdummyparameter\c!factor,%
+ scale=\directdummyparameter\c!scale,%
+ xstep=\directdummyparameter\c!xstep,%
+ ystep=\directdummyparameter\c!ystep,%
+ xoffset=\directdummyparameter\c!xoffset,%
+ yoffset=\directdummyparameter\c!yoffset,%
+ align=\p_align}%
+ \egroup}
+
+\let\grid\basegrid
+
+\protect \endinput
diff --git a/tex/context/base/meta-imp-dum.mkiv b/tex/context/base/meta-imp-dum.mkiv
index a622d94f4..83fe12f09 100644
--- a/tex/context/base/meta-imp-dum.mkiv
+++ b/tex/context/base/meta-imp-dum.mkiv
@@ -59,7 +59,7 @@
% clip currentpicture to p ;
% \stopuseMPgraphic
-\startuseMPgraphic{placeholder}{width,height,reduction,color}
+\startuseMPgraphic{figure:placeholder}{width,height,reduction,color}
numeric w, h, d, r ; path p ;
if cmykcolor \MPvar{color} :
cmykcolor c, b ; b := (0,0,0,0)
@@ -82,66 +82,79 @@
clip currentpicture to p ;
\stopuseMPgraphic
+\defineoverlay
+ [figure:placeholder:graphic]
+ [\useMPgraphic
+ {figure:placeholder}%
+ {width=\figurewidth,%
+ height=\figureheight,%
+ reduction=\externalfigureparameter\c!reduction,%
+ color=placeholder:\the\c_grph_replacement_n}]
+
\definepalet
[placeholder]
[1=red,2=green,3=blue,4=cyan,5=magenta,6=yellow]
-% \newcounter \figurereplacementcycle
-
-\let\figurereplacementcycle\relax
+\newcount\c_grph_replacement_n
\setupexternalfigures
[\c!reduction=0,
\c!text=\v!yes]
-\let\normalexternalfigurereplacement\externalfigurereplacement
+\let\grph_include_replacement_saved\grph_include_replacement
-\unexpanded\def\externalfigurereplacement#1#2#3%
- {\getpaletsize[placeholder]%
- \ifx\figurereplacementcycle\relax
- \getrandomnumber \figurereplacementcycle \!!plusone \paletsize
- \globallet \figurereplacementcycle \figurereplacementcycle
+\unexpanded\def\grph_include_replacement#1#2#3%
+ {\begingroup
+ \getpaletsize[placeholder]%
+ \ifnum\c_grph_replacement_n=\zerocount
+ \getrandomnumber \m_grph_replacement_n\plusone\paletsize
+ \global\c_grph_replacement_n \m_grph_replacement_n\relax
\else
- \doglobal\increment\figurereplacementcycle
+ \global\advance\c_grph_replacement_n\plusone
\fi
- \ifnum\figurereplacementcycle>\paletsize
- \globallet\figurereplacementcycle\!!plusone
+ \ifnum\c_grph_replacement_n>\paletsize
+ \global\c_grph_replacement_n\plusone
\fi
- \defineoverlay
- [\s!dummy]
- [\useMPgraphic
- {placeholder}%
- {width=\figurewidth,
- height=\figureheight,
- reduction=\@@efreduction,
- color=placeholder:\figurereplacementcycle}]%
- \expanded{\localframed
- [\??ef]
+ \setupcurrentexternalfigure
[\c!width=\figurewidth,
\c!height=\figureheight,
\c!frame=\v!off,
\c!strut=\v!no,
- \c!background=\s!dummy,
- \c!foregroundcolor=\s!white]}%
- {\doif\@@eftext\v!yes
- {\infofont \setupinterlinespace \dohyphens % \nohyphens
- \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
- \ifx\tempb\empty\else
- \ifx\tempa\empty\ifx\tempc\empty\else file: \fi\else file: \fi
- \expanded{\verbatimstring{#2}}\strut\endgraf
- \fi
- \ifx\tempc\empty\else
- state: \expanded{\verbatimstring{#3}}\strut\endgraf
- \fi}}}
+ \c!background=figure:placeholder:graphic,
+ \c!foregroundcolor=\s!white]%
+ \doifelse{\externalfigureparameter\c!text}\v!yes
+ {\edef\m_graphics_text_a{#1}\edef\m_graphics_text_a{\ifx\m_graphics_text_a\s!dummy\else\detokenize\expandafter{\m_graphics_text_a}\fi}%
+ \edef\m_graphics_text_b{#2}\edef\m_graphics_text_b{\ifx\m_graphics_text_b\s!dummy\else\detokenize\expandafter{\m_graphics_text_b}\fi}%
+ \edef\m_graphics_text_c{#3}\edef\m_graphics_text_c{\ifx\m_graphics_text_c\s!dummy\else\detokenize\expandafter{\m_graphics_text_c}\fi}%
+ \infofont\setupinterlinespace\dohyphens
+ \inheritedexternalfigureframed{\directsetup{figure:placeholder:text}}}%
+ {\inheritedexternalfigureframed{}}%
+ \endgroup}
\unexpanded\def\dummyfigure
{\externalfigure[placeholder]}
+\startsetups figure:placeholder:text
+ \ifx\m_graphics_text_a\empty\else
+ \strut name: \m_graphics_text_a\par
+ \fi
+ \ifx\m_graphics_text_b\empty\else
+ \strut
+ \ifx\m_graphics_text_a\empty
+ \ifx\m_graphics_text_c\empty
+ \else
+ file:\space
+ \fi
+ \else
+ file:\space
+ \fi
+ \m_graphics_text_b\par
+ \fi
+ \ifx\m_graphics_text_c\empty\else
+ \strut state: \m_graphics_text_c\par
+ \fi
+\stopsetups
+
%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]
@@ -151,7 +164,7 @@
\defineframed
[figurecomment]
[\c!background=\v!color,
- \c!backgroundcolor=\v!gray,
+ \c!backgroundcolor=\s!gray,
\c!frame=\v!off,
\c!foregroundstyle=\ttbf,
\c!align={\v!middle,\v!lohi},
@@ -160,8 +173,8 @@
\defineframed
[figuredummy]
- [\c!background=figure:placeholder,
- \c!foregroundcolor=white,
+ [\c!background=figure:dummy,
+ \c!foregroundcolor=\s!white,
\c!backgroundcolor=\v!gray,
\c!frame=\v!off,
\c!foregroundstyle=\ttbf,
@@ -170,18 +183,30 @@
\c!width=\figurewidth]
\defineoverlay
- [figure:placeholder]
- [\externalfigurereplacement{}{}{}]
+ [figure:dummy]
+ [\grph_include_replacement\empty\empty\empty]
\defineoverlay
[figure:comment]
- [\figurecomment{\@@efcomment}]
+ [\figurecomment{\externalfigureparameter\c!comment}]
\defineoverlay
[figure:dummy]
- [\figuredummy{\@@efcomment}]
+ [\figuredummy{\externalfigureparameter\c!comment}]
\setupexternalfigures
- [comment=]
+ [\c!comment=]
+
+\protect
+
+\continueifinputfile{meta-imp-dum.mkiv}
+
+\starttext
+
+ \externalfigure[whatever-missing]
+
+ \blank
+
+ \externalfigure[whatever-missing][width=2cm]
-\protect \endinput
+\stoptext
diff --git a/tex/context/base/meta-ini.lua b/tex/context/base/meta-ini.lua
index bac1429ae..8b6fd22a2 100644
--- a/tex/context/base/meta-ini.lua
+++ b/tex/context/base/meta-ini.lua
@@ -9,6 +9,8 @@ if not modules then modules = { } end modules ['meta-ini'] = {
local tonumber = tonumber
local format, gmatch, match, gsub = string.format, string.gmatch, string.match, string.gsub
+local context = context
+
metapost = metapost or { }
-- for the moment downward compatible
diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv
index a62b81ccf..cd4e03bd6 100644
--- a/tex/context/base/meta-ini.mkiv
+++ b/tex/context/base/meta-ini.mkiv
@@ -104,14 +104,6 @@
\c!textstyle=,
\c!textcolor=]
-% \unexpanded\def\defineMPinstance
-% {\dodoubleargument\meta_define_instance}
-
-% \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]}
-
\appendtoks
\ifcsname\??mpinstancetokens\currentMPinstance\endcsname \else
\expandafter\newtoks\csname\??mpinstancetokens\currentMPinstance\endcsname
@@ -192,22 +184,43 @@
{\global\t_meta_instance\emptytoks
\endgroup}
+\def\meta_process_graphic_start
+ {\setbox\b_meta_graphic\hbox\bgroup}
+
+\def\meta_process_graphic_stop
+ {\egroup
+ \meta_place_graphic}
+
\unexpanded\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig
{\meta_start_current_graphic
\forgetall
- \setbox\b_meta_graphic\hbox\bgroup % ; added 20100901 (as in mkii)
+ \meta_process_graphic_start
\normalexpanded{\noexpand\ctxlua{metapost.graphic(
"\currentMPinstance",
"\currentMPformat",
\!!bs#1;\!!es,
\!!bs\meta_flush_current_initializations;\!!es,
\!!bs\meta_flush_current_preamble;\!!es,
- \MPaskedfigure
+ "\MPaskedfigure"
)}}%
- \egroup
- \placeMPgraphic
+ \meta_process_graphic_stop
\meta_stop_current_graphic}
+\let\meta_process_graphic_figure_start\relax
+\let\meta_process_graphic_figure_stop \relax
+
+\unexpanded\def\processMPfigurefile#1% special case: obeys beginfig .. endfig and makes pages
+ {\begingroup
+ \let\normal_meta_process_graphic_start\meta_process_graphic_start
+ \let\normal_meta_process_graphic_stop \meta_process_graphic_stop
+ \let\meta_process_graphic_start\relax
+ \let\meta_process_graphic_stop \relax
+ \def\meta_process_graphic_figure_start{\startTEXpage\normal_meta_process_graphic_start}%
+ \def\meta_process_graphic_figure_stop {\normal_meta_process_graphic_stop\stopTEXpage}
+ \def\MPaskedfigure{all}%
+ \meta_process_graphic{input "#1" ;}%
+ \endgroup}
+
\newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default
\def\setMPrandomseed
@@ -362,34 +375,36 @@
\let \m_meta_current_variable \empty
\let \m_meta_current_variable_template\empty
+\installcorenamespace{graphicvariable}
+
\def \meta_prepare_variable_default {\MPcolor{black}} % just to be sure we use a color but ...
-\edef\meta_unknown_variable_template {\??gv:\s!unknown}
+\edef\meta_unknown_variable_template {\??graphicvariable:\s!unknown}
-\letvalue{\??gv:\s!unknown}\empty
+\letvalue{\??graphicvariable:\s!unknown}\empty
\unexpanded\def\setupMPvariables
{\dodoubleempty\meta_setup_variables}
\def\meta_setup_variables[#1][#2]%
{\ifsecondargument
- \getrawparameters[\??gv#1:][#2]%
+ \getrawparameters[\??graphicvariable#1:][#2]%
\else
- \getrawparameters[\??gv:][#1]%
+ \getrawparameters[\??graphicvariable:][#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}%
+ {\ifcsname\??graphicvariable#1:#2\endcsname \else
+ \setvalue{\??graphicvariable#1:#2}{#3}%
\fi}
\def\MPrawvar#1#2% no checking
- {\csname\??gv#1:#2\endcsname}
+ {\csname\??graphicvariable#1:#2\endcsname}
\def\MPvariable#1% todo: could be a framed chain
- {\csname\??gv\currentmpvariableclass:#1\endcsname}
+ {\csname\??graphicvariable\currentmpvariableclass:#1\endcsname}
\unexpanded\def\useMPvariables
{\dodoubleargument\meta_use_variables}
@@ -403,7 +418,7 @@
\unexpanded\def\meta_prepare_variable#1%
{\edef\m_meta_current_variable_template
- {\??gv\currentmpvariableclass:#1}%
+ {\??graphicvariable\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
@@ -506,7 +521,7 @@
\let\meta_relocate_box\relax
-\unexpanded\def\placeMPgraphic % the converter also displaces so in fact we revert
+\unexpanded\def\meta_place_graphic % the converter also displaces so in fact we revert
{\meta_relocate_box
\box\b_meta_graphic}
@@ -1172,11 +1187,9 @@
%D
%D Here is a generic setup command:
-\newtoks\everysetupMPgraphics
+\installcorenamespace{MPgraphics}
-\unexpanded\def\setupMPgraphics[#1]%
- {\getparameters[\??mp][#1]%
- \the\everysetupMPgraphics}
+\installsetuponlycommandhandler \??MPgraphics {MPgraphics}
%D Here we hook in the outer color. When \type {color} is set to \type
%D {global} we get the outer color automatically. If you change this
@@ -1184,7 +1197,7 @@
%D behave in unexpected ways.
\appendtoks
- \doifelse\@@mpcolor\v!global{\MPcolormethod\plusone}{\MPcolormethod\zerocount}%
+ \doifelse{\directMPgraphicsparameter\c!color}\v!global{\MPcolormethod\plusone}{\MPcolormethod\zerocount}%
\to \everysetupMPgraphics
\setupMPgraphics
diff --git a/tex/context/base/meta-pag.mkiv b/tex/context/base/meta-pag.mkiv
index 6cea270e3..ef53d4753 100644
--- a/tex/context/base/meta-pag.mkiv
+++ b/tex/context/base/meta-pag.mkiv
@@ -33,6 +33,12 @@
\stopMPinitializations
\startMPinitializations
+ CurrentColumn:=\number\mofcolumns;
+ NOfColumns:=\number\nofcolumns;
+ % todo: ColumnDistance
+\stopMPinitializations
+
+\startMPinitializations
def LoadPageState =
OnRightPage:=\MPonrightpage;
OnOddPage:=\MPonoddpage;
@@ -75,8 +81,8 @@
InnerEdgeWidth:=\the\inneredgewidth;
OuterEdgeDistance:=\the\outeredgedistance;
OuterEdgeWidth:=\the\outeredgewidth;
- PageOffset:=\the\pageoffset;
- PageDepth:=\the\pagedepth;
+ PageOffset:=\the\pagebackgroundoffset;
+ PageDepth:=\the\pagebackgrounddepth;
LayoutColumns:=\the\layoutcolumns;
LayoutColumnDistance:=\the\layoutcolumndistance;
LayoutColumnWidth:=\the\layoutcolumnwidth;
diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua
index 13d39e445..c68350a96 100644
--- a/tex/context/base/meta-pdf.lua
+++ b/tex/context/base/meta-pdf.lua
@@ -9,6 +9,9 @@ if not modules then modules = { } end modules ['meta-pdf'] = {
-- Finally we used an optimized version. The test code can be found in
-- meta-pdh.lua but since we no longer want to overload functione we use
-- more locals now. This module keeps changing as it is also a testbed.
+--
+-- We can make it even more efficient if needed, but as we don't use this
+-- code often in \MKIV\ it makes no sense.
local concat, format, gsub, find, byte, gmatch, match = table.concat, string.format, string.gsub, string.find, string.byte, string.gmatch, string.match
local lpegmatch = lpeg.match
@@ -50,8 +53,8 @@ end
resetall()
--- -- this does not work as expected (displacement of text)
--- -- beware, needs another comment hack
+-- -- this does not work as expected (displacement of text) beware, needs another
+-- -- comment hack
--
-- local function pdfcode(str)
-- context(pdfliteral(str))
diff --git a/tex/context/base/meta-pdh.mkiv b/tex/context/base/meta-pdh.mkiv
index 6d85a8dc1..b65fe6ac6 100644
--- a/tex/context/base/meta-pdh.mkiv
+++ b/tex/context/base/meta-pdh.mkiv
@@ -565,7 +565,7 @@
% {\ifcase\pdfoutput\or % will be hooked into the special driver
% \doiffileelse{#7}
% {\doifundefinedelse{mps:x:#7}
-% {\immediate\pdfximage\!!width\onebasepoint\!!height\onebasepoint{#7}%
+% {\immediate\pdfximage\s!width\onebasepoint\s!height\onebasepoint{#7}%
% \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}}%
% {\message{[reusing figure #7]}}%
% \pdfliteral{q #1 #2 #3 #4 #5 #6 cm}%
diff --git a/tex/context/base/meta-tex.lua b/tex/context/base/meta-tex.lua
index 872e8154c..c29498ad1 100644
--- a/tex/context/base/meta-tex.lua
+++ b/tex/context/base/meta-tex.lua
@@ -31,7 +31,7 @@ if not modules then modules = { } end modules ['meta-tex'] = {
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
-local pattern = Cs((P([[\"]]) + P([["]])/"\\quotedbl{}" + P(1))^0)
+local pattern = Cs((P([[\"]]) + P([["]])/"\\quotedbl{}" + P(1))^0) -- or \char
function metapost.escaped(str)
context(lpegmatch(pattern,str))
diff --git a/tex/context/base/mlib-ctx.lua b/tex/context/base/mlib-ctx.lua
index 493a45248..a8ef84b80 100644
--- a/tex/context/base/mlib-ctx.lua
+++ b/tex/context/base/mlib-ctx.lua
@@ -97,9 +97,11 @@ local environments = { }
function metapost.tex.set(str)
environments[#environments+1] = str
end
+
function metapost.tex.reset()
environments = { }
end
+
function metapost.tex.get()
return concat(environments,"\n")
end
diff --git a/tex/context/base/mlib-pdf.lua b/tex/context/base/mlib-pdf.lua
index 7a23ba947..88f26e755 100644
--- a/tex/context/base/mlib-pdf.lua
+++ b/tex/context/base/mlib-pdf.lua
@@ -11,26 +11,41 @@ local abs, sqrt, round = math.abs, math.sqrt, math.round
local setmetatable = setmetatable
local Cf, C, Cg, Ct, P, S, lpegmatch = lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.match
-local allocate = utilities.storage.allocate
-
local report_metapost = logs.reporter("metapost")
local mplib, context = mplib, context
-local copy_node = node.copy
-local write_node = node.write
+local allocate = utilities.storage.allocate
+
+local copy_node = node.copy
+local write_node = node.write
+
+metapost = metapost or { }
+local metapost = metapost
+
+metapost.flushers = metapost.flushers or { }
+local pdfflusher = { }
+metapost.flushers.pdf = pdfflusher
-metapost = metapost or { }
-local metapost = metapost
+metapost.multipass = false
+metapost.n = 0
+metapost.optimize = true -- false
-metapost.multipass = false
-metapost.n = 0
-metapost.optimize = true -- false
+local experiment = true -- uses context(node) that already does delayed nodes
+
+local savedliterals = nil -- needs checking
+local mpsliteral = nodes.pool.register(node.new("whatsit",nodes.whatsitcodes.pdfliteral)) -- pdfliteral.mode = 1
+
+local pdfliteral = function(s)
+ local literal = copy_node(mpsliteral)
+ literal.data = s
+ return literal
+end
---~ Because in MKiV we always have two passes, we save the objects. When an extra
---~ mp run is done (due to for instance texts identifier in the parse pass), we
---~ get a new result table and the stored objects are forgotten. Otherwise they
---~ are reused.
+-- Because in MKiV we always have two passes, we save the objects. When an extra
+-- mp run is done (due to for instance texts identifier in the parse pass), we
+-- get a new result table and the stored objects are forgotten. Otherwise they
+-- are reused.
local function getobjects(result,figure,f)
if metapost.optimize then
@@ -64,23 +79,6 @@ function metapost.convert(result, trialrun, flusher, multipass, askedfig)
return true -- done
end
-metapost.flushers = { }
-metapost.flushers.pdf = { }
-
--- \def\MPLIBtoPDF#1{\ctxlua{metapost.flushliteral(#1)}}
-
-local savedliterals = nil -- needs checking
-
-local mpsliteral = nodes.pool.register(node.new("whatsit",8)) -- pdfliteral
-
-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)
@@ -95,7 +93,7 @@ function metapost.flushreset() -- will become obsolete and internal
savedliterals = nil
end
-function metapost.flushers.pdf.comment(message)
+function pdfflusher.comment(message)
if message then
message = format("%% mps graphic %s: %s", metapost.n, message)
if experiment then
@@ -113,20 +111,20 @@ function metapost.flushers.pdf.comment(message)
end
end
-function metapost.flushers.pdf.startfigure(n,llx,lly,urx,ury,message)
+function pdfflusher.startfigure(n,llx,lly,urx,ury,message)
savedliterals = nil
metapost.n = metapost.n + 1
context.startMPLIBtoPDF(llx,lly,urx,ury)
- if message then metapost.flushers.pdf.comment(message) end
+ if message then pdfflusher.comment(message) end
end
-function metapost.flushers.pdf.stopfigure(message)
- if message then metapost.flushers.pdf.comment(message) end
+function pdfflusher.stopfigure(message)
+ if message then pdfflusher.comment(message) end
context.stopMPLIBtoPDF()
context.MPLIBflushreset() -- maybe just at the beginning
end
-function metapost.flushers.pdf.flushfigure(pdfliterals) -- table
+function pdfflusher.flushfigure(pdfliterals) -- table
if #pdfliterals > 0 then
pdfliterals = concat(pdfliterals,"\n")
if experiment then
@@ -144,7 +142,7 @@ function metapost.flushers.pdf.flushfigure(pdfliterals) -- table
end
end
-function metapost.flushers.pdf.textfigure(font,size,text,width,height,depth) -- we could save the factor
+function pdfflusher.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.MPtextext(font,size,text,0,-number.dimenfactors.bp*depth)
end
@@ -273,7 +271,7 @@ function metapost.flush(result,flusher,askedfig)
if result then
local figures = result.fig
if figures then
- flusher = flusher or metapost.flushers.pdf
+ flusher = flusher or pdfflusher
local resetplugins = metapost.resetplugins or ignore -- before figure
local processplugins = metapost.processplugins or ignore -- each object
local synchronizeplugins = metapost.synchronizeplugins or ignore
@@ -290,7 +288,7 @@ function metapost.flush(result,flusher,askedfig)
local t = { }
local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
local bbox = figure:boundingbox()
- local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
+ local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4]
metapost.llx = llx
metapost.lly = lly
metapost.urx = urx
@@ -451,24 +449,17 @@ function metapost.parse(result,askedfig)
local figures = result.fig
if figures then
local analyzeplugins = metapost.analyzeplugins -- each object
- for f=1, #figures do
+ for f=1,#figures do
local figure = figures[f]
local fignum = figure:charcode() or 0
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
- metapost.lly = lly
- metapost.urx = urx
- metapost.ury = ury
+ metapost.llx = bbox[1]
+ metapost.lly = bbox[2]
+ metapost.urx = bbox[3]
+ metapost.ury = bbox[4]
local objects = getobjects(result,figure,f)
if objects then
- -- for o=1,#objects do
- -- local object = objects[o]
- -- local prescript = object.prescript
- -- if prescript then
- -- analyzeplugins(object)
- -- end
for o=1,#objects do
analyzeplugins(objects[o])
end
diff --git a/tex/context/base/mlib-pdf.mkiv b/tex/context/base/mlib-pdf.mkiv
index b9871eead..68b4b922a 100644
--- a/tex/context/base/mlib-pdf.mkiv
+++ b/tex/context/base/mlib-pdf.mkiv
@@ -91,7 +91,8 @@
\def\MPLIBtoPDF#1{\ctxlua{metapost.flushliteral(#1)}}
\def\startMPLIBtoPDF#1#2#3#4%
- {\dostarttagged\t!mpgraphic\empty
+ {\meta_process_graphic_figure_start
+ \dostarttagged\t!mpgraphic\empty
\naturalhbox attr \imageattribute 1 \bgroup
\dousecolorparameter\s!black\forcecolorhack
\setMPboundingbox{#1}{#2}{#3}{#4}%
@@ -104,7 +105,8 @@
\finalizeMPbox
\box\MPbox
\egroup
- \dostoptagged}
+ \dostoptagged
+ \meta_process_graphic_figure_stop}
\def\MPLIBflushreset % This can (will) move to the Lua end.
{\ctxlua{metapost.flushreset()}}
diff --git a/tex/context/base/mlib-pps.mkiv b/tex/context/base/mlib-pps.mkiv
index cb6120066..704c9e635 100644
--- a/tex/context/base/mlib-pps.mkiv
+++ b/tex/context/base/mlib-pps.mkiv
@@ -64,13 +64,15 @@
\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
+% \scale[\c!sx=#8,\c!sy=#9]{\raise\dp\MPtextbox\box\MPtextbox}%
+% \scale[\c!sx=#8,\c!sy=#9,\c!depth=\v!no]{\box\MPtextbox}%
+ \fastsxsy{#8}{#9}{\raise\dp\MPtextbox\box\MPtextbox}%
+ % This gives: LuaTeX warning: Misplaced \pdfrestore .. don't ask me why.
+ % but I'll retry it some day soon.
+ % \dostartscaling{#8}{#9}%
+ % \raise\dp\MPtextbox\box\MPtextbox
+ % \dostopscaling
+ \forcecolorhack % needed ? already in the scale macro
\hss
\egroup
\egroup
diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua
index 59dc88b90..08ed22e47 100644
--- a/tex/context/base/mlib-run.lua
+++ b/tex/context/base/mlib-run.lua
@@ -29,29 +29,29 @@ approach is way faster than an external <l n='metapost'/> and processing time
nears zero.</p>
--ldx]]--
+local format, gsub, match, find = string.format, string.gsub, string.match, string.find
+local emptystring = string.is_empty
+local lpegmatch, P = lpeg.match, lpeg.P
+
local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end)
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
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
-local mplib = mplib
+local mplib = mplib
+metapost = metapost or { }
+local metapost = metapost
-metapost = metapost or { }
-local metapost = metapost
+local mplibone = tonumber(mplib.version()) <= 1.50
metapost.showlog = false
metapost.lastlog = ""
metapost.texerrors = false
metapost.exectime = metapost.exectime or { } -- hack
-local mplibone = tonumber(mplib.version()) <= 1.50
-
directives.register("mplib.texerrors", function(v) metapost.texerrors = v end)
function metapost.resetlastlog()
@@ -68,19 +68,57 @@ end
-- 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
+----- mpbasepath = lpeg.instringchecker(lpeg.append { "/metapost/context/", "/metapost/base/" })
+local mpbasepath = lpeg.instringchecker(P("/metapost/") * (P("context") + P("base")) * P("/"))
+
+-- local function i_finder(askedname,mode,ftype) -- fake message for mpost.map and metafun.mpvi
+-- local foundname = file.is_qualified_path(askedname) and askedname or resolvers.findfile(askedname,ftype)
+-- if not mpbasepath(foundname) then
+-- -- we could use the via file but we don't have a complete io interface yet
+-- local data, found, forced = metapost.checktexts(io.loaddata(foundname) or "")
+-- if found then
+-- local tempname = luatex.registertempfile(foundname,true)
+-- io.savedata(tempname,data)
+-- foundname = tempname
+-- end
+-- end
+-- return foundname
+-- end
+
+-- mplib has no real io interface so we have a different mechanism than
+-- tex (as soon as we have more control, we will use the normal code)
+
+local finders = { }
+mplib.finders = finders
+
+-- for some reason mp sometimes calls this function twice which is inefficient
+-- but we cannot catch this
+
+local function preprocessed(name)
+ if not mpbasepath(name) then
+ -- we could use the via file but we don't have a complete io interface yet
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
+ return temp
end
end
return name
end
+mplib.preprocessed = preprocessed -- helper
+
+finders.file = function(specification,name,mode,ftype)
+ return preprocessed(resolvers.findfile(name,ftype))
+end
+
+local function i_finder(name,mode,ftype) -- fake message for mpost.map and metafun.mpvi
+ local specification = url.hashed(name)
+ local finder = finders[specification.scheme] or finders.file
+ return finder(specification,name,mode,ftype)
+end
+
local function o_finder(name, mode, ftype)
return name
end
@@ -145,99 +183,103 @@ end
if mplibone then
- local preamble = [[
- boolean mplib ; mplib := true ;
- string mp_parent_version ; mp_parent_version := "%s" ;
- input "%s" ; dump ;
- ]]
-
- metapost.parameters = {
- hash_size = 100000,
- main_memory = 4000000,
- max_in_open = 50,
- param_size = 100000,
- }
-
- function metapost.make(name, target, version)
- starttiming(mplib)
- target = file.replacesuffix(target or name, "mem") -- redundant
- local mpx = mplib.new ( table.merged (
- metapost.parameters,
- {
- ini_version = true,
- find_file = finder,
- job_name = file.removesuffix(target),
- }
- ) )
- if mpx then
- starttiming(metapost.exectime)
- local result = mpx:execute(format(preamble,version or "unknown",name))
- stoptiming(metapost.exectime)
- mpx:finish()
- end
- stoptiming(mplib)
- end
-
- function metapost.load(name)
- starttiming(mplib)
- local mpx = mplib.new ( table.merged (
- metapost.parameters,
- {
- ini_version = false,
- mem_name = file.replacesuffix(name,"mem"),
- find_file = finder,
- -- job_name = "mplib",
- }
- ) )
- local result
- if not mpx then
- result = { status = 99, error = "out of memory"}
- end
- stoptiming(mplib)
- return mpx, result
- end
-
- function metapost.checkformat(mpsinput)
- local mpsversion = environment.version or "unset version"
- local mpsinput = file.addsuffix(mpsinput or "metafun", "mp")
- local mpsformat = file.removesuffix(file.basename(texconfig.formatname or (tex and tex.formatname) or mpsinput))
- local mpsbase = file.removesuffix(file.basename(mpsinput))
- if mpsbase ~= mpsformat then
- mpsformat = mpsformat .. "-" .. mpsbase
- end
- mpsformat = file.addsuffix(mpsformat, "mem")
- local mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats") or ""
- if mpsformatfullname ~= "" then
- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname)
- local mpx, result = metapost.load(mpsformatfullname)
- if mpx then
- local result = mpx:execute("show mp_parent_version ;")
- if not result.log then
- metapost.reporterror(result)
- else
- local version = match(result.log,">> *(.-)[\n\r]") or "unknown"
- version = gsub(version,"[\'\"]","")
- if version ~= mpsversion then
- report_metapost("version mismatch: %s <> %s", version or "unknown", mpsversion)
- else
- return mpx
- end
- end
- else
- report_metapost("error in loading '%s' from '%s'", mpsinput, mpsformatfullname)
- metapost.reporterror(result)
- end
- end
- local mpsformatfullname = caches.setfirstwritablefile(mpsformat,"formats")
- report_metapost("making '%s' into '%s'", mpsinput, mpsformatfullname)
- metapost.make(mpsinput,mpsformatfullname,mpsversion) -- somehow return ... fails here
- if lfs.isfile(mpsformatfullname) then
- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname)
- return metapost.load(mpsformatfullname)
- else
- report_metapost("problems with '%s' from '%s'", mpsinput, mpsformatfullname)
- end
- end
+ report_metapost("fatal error: mplib is too old")
+
+ os.exit()
+
+ -- local preamble = [[
+ -- boolean mplib ; mplib := true ;
+ -- string mp_parent_version ; mp_parent_version := "%s" ;
+ -- input "%s" ; dump ;
+ -- ]]
+ --
+ -- metapost.parameters = {
+ -- hash_size = 100000,
+ -- main_memory = 4000000,
+ -- max_in_open = 50,
+ -- param_size = 100000,
+ -- }
+ --
+ -- function metapost.make(name, target, version)
+ -- starttiming(mplib)
+ -- target = file.replacesuffix(target or name, "mem") -- redundant
+ -- local mpx = mplib.new ( table.merged (
+ -- metapost.parameters,
+ -- {
+ -- ini_version = true,
+ -- find_file = finder,
+ -- job_name = file.removesuffix(target),
+ -- }
+ -- ) )
+ -- if mpx then
+ -- starttiming(metapost.exectime)
+ -- local result = mpx:execute(format(preamble,version or "unknown",name))
+ -- stoptiming(metapost.exectime)
+ -- mpx:finish()
+ -- end
+ -- stoptiming(mplib)
+ -- end
+ --
+ -- function metapost.load(name)
+ -- starttiming(mplib)
+ -- local mpx = mplib.new ( table.merged (
+ -- metapost.parameters,
+ -- {
+ -- ini_version = false,
+ -- mem_name = file.replacesuffix(name,"mem"),
+ -- find_file = finder,
+ -- -- job_name = "mplib",
+ -- }
+ -- ) )
+ -- local result
+ -- if not mpx then
+ -- result = { status = 99, error = "out of memory"}
+ -- end
+ -- stoptiming(mplib)
+ -- return mpx, result
+ -- end
+ --
+ -- function metapost.checkformat(mpsinput)
+ -- local mpsversion = environment.version or "unset version"
+ -- local mpsinput = file.addsuffix(mpsinput or "metafun", "mp")
+ -- local mpsformat = file.removesuffix(file.basename(texconfig.formatname or (tex and tex.formatname) or mpsinput))
+ -- local mpsbase = file.removesuffix(file.basename(mpsinput))
+ -- if mpsbase ~= mpsformat then
+ -- mpsformat = mpsformat .. "-" .. mpsbase
+ -- end
+ -- mpsformat = file.addsuffix(mpsformat, "mem")
+ -- local mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats") or ""
+ -- if mpsformatfullname ~= "" then
+ -- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname)
+ -- local mpx, result = metapost.load(mpsformatfullname)
+ -- if mpx then
+ -- local result = mpx:execute("show mp_parent_version ;")
+ -- if not result.log then
+ -- metapost.reporterror(result)
+ -- else
+ -- local version = match(result.log,">> *(.-)[\n\r]") or "unknown"
+ -- version = gsub(version,"[\'\"]","")
+ -- if version ~= mpsversion then
+ -- report_metapost("version mismatch: %s <> %s", version or "unknown", mpsversion)
+ -- else
+ -- return mpx
+ -- end
+ -- end
+ -- else
+ -- report_metapost("error in loading '%s' from '%s'", mpsinput, mpsformatfullname)
+ -- metapost.reporterror(result)
+ -- end
+ -- end
+ -- local mpsformatfullname = caches.setfirstwritablefile(mpsformat,"formats")
+ -- report_metapost("making '%s' into '%s'", mpsinput, mpsformatfullname)
+ -- metapost.make(mpsinput,mpsformatfullname,mpsversion) -- somehow return ... fails here
+ -- if lfs.isfile(mpsformatfullname) then
+ -- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname)
+ -- return metapost.load(mpsformatfullname)
+ -- else
+ -- report_metapost("problems with '%s' from '%s'", mpsinput, mpsformatfullname)
+ -- end
+ -- end
else
@@ -350,8 +392,9 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
if trace_graphics then
if not mp_inp[mpx] then
mp_tag = mp_tag + 1
- mp_inp[mpx] = io.open(format("%s-mplib-run-%03i.mp", tex.jobname,mp_tag),"w")
- mp_log[mpx] = io.open(format("%s-mplib-run-%03i.log",tex.jobname,mp_tag),"w")
+ local jobname = tex.jobname
+ mp_inp[mpx] = io.open(format("%s-mplib-run-%03i.mp", jobname,mp_tag),"w")
+ mp_log[mpx] = io.open(format("%s-mplib-run-%03i.log",jobname,mp_tag),"w")
end
local banner = format("%% begin graphic: n=%s, trialrun=%s, multipass=%s, isextrapass=%s\n\n", metapost.n, tostring(trialrun), tostring(multipass), tostring(isextrapass))
mp_inp[mpx]:write(banner)
diff --git a/tex/context/base/mult-aux.lua b/tex/context/base/mult-aux.lua
index e0fd87a02..911888991 100644
--- a/tex/context/base/mult-aux.lua
+++ b/tex/context/base/mult-aux.lua
@@ -43,7 +43,7 @@ function namespaces.define(namespace,settings)
local self = "\\" .. prefix .. namespace
context.unprotect()
-- context.installnamespace(namespace)
- context("\\def\\%s%s{%s%s}",prefix,namespace,meaning,namespace)
+ context("\\def\\%s%s{%s%s}",prefix,namespace,meaning,namespace) -- or context.setvalue
if trace_namespaces then
report_namespaces("using namespace '%s' for '%s'",namespace,name)
end
diff --git a/tex/context/base/mult-aux.mkiv b/tex/context/base/mult-aux.mkiv
index b4c6ad039..dc6aca920 100644
--- a/tex/context/base/mult-aux.mkiv
+++ b/tex/context/base/mult-aux.mkiv
@@ -2,7 +2,7 @@
%D [ file=mult-aux,
%D version=2010.08.2,
%D title=\CONTEXT\ Multilingual Macros,
-%D subtitle=helpers,
+%D subtitle=Helpers,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
@@ -14,6 +14,9 @@
% todo: setupxxx and setupxxxs (so a plural for the root setup and
% we can consider blocking the root)
+% todo (e.g for columnsets and registers): \definexxx[parent][1]
+%
+
%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.
@@ -41,7 +44,7 @@
%D % \whateverparameter \c!test
%D % \whateverparameterhash \c!test
%D % \namedwhateverparameter \mycurrentwhatever \c!test
-%D % \dosetwhateverstyleandcolor \c!style \c!color
+%D % \usewhateverstyleandcolor \c!style \c!color
%D % \everydefinewhatever (sets \currentwhatever)
%D % \everypresetwhatever (can be used to reset parameters as we can redefine)
%D % \everysetupwhatever (sets \currentwhatever)
@@ -93,12 +96,8 @@
\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@}
+ {\mult_interfaces_get_parameters_item#1,],\_e_o_p_}
\def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before ,
{\if,#1,% dirty trick for testing #1=empty
@@ -106,14 +105,14 @@
\else\if]#1%
\doubleexpandafter\gobbleoneargument
\else
- \mult_interfaces_get_parameters_assign#1==\empty\@relax@
+ \mult_interfaces_get_parameters_assign#1==\empty\_e_o_p_
\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@
+\def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
{\ifx\empty#1\empty
\expandafter\mult_interfaces_get_parameters_error
\else\ifx#3\empty
@@ -125,21 +124,35 @@
\newif\ifassignment
-\def\mult_check_for_assignment#1=#2#3\_end_
- {\expandafter\if\detokenize{#2}@\assignmentfalse\else\assignmenttrue\fi}
+\def\mult_check_for_assignment_indeed#1=#2#3\_end_
+ {\if#2@\assignmentfalse\else\assignmenttrue\fi}
-% usage: \mult_check_for_assignment##1=@@_end_
+\def\mult_check_for_assignment#1%
+ {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_}
% End of experimental code.
+% the commented detokenized variant that backtracks ... needs testing usage first
+%
+% \let\whatever\relax
+%
+% \definetest[oeps][bagger=\whatever]
+%
+% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par
+% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par
+
+\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}
+
\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
+ {\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#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version
+ % \def#7##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
\def#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}%
\def#9##1{\csname#1#2:##1\endcsname}}
@@ -251,30 +264,34 @@
\let\definehandlerparent\empty
-\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\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones
+ {\ifx#4\relax\let#4\empty\fi % see \defineregister
\unexpanded\def#2{\dotripleempty#5}%
\newtoks#6%
\newtoks#7%
- \def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
+ \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
{\let#9#4%
\edef#4{##1}%
- \the#6% predefine
\ifthirdargument
+ \the#6% predefine
\edef#8{##2}%
- \mult_interfaces_get_parameters{#1#4:}[\s!parent=#1##2,##3]%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
+ \mult_interfaces_get_parameters{#1#4:}[##3]%
\else\ifsecondargument
- \mult_check_for_assignment##2=@@\_end_
+ \the#6% predefine
+ \expandafter\mult_check_for_assignment_indeed\detokenize{##2}=@@\_end_
\ifassignment
\let#8\empty
- \mult_interfaces_get_parameters{#1#4:}[\s!parent=#3,##2]%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
+ \mult_interfaces_get_parameters{#1#4:}[##2]%
\else
\edef#8{##2}%
- \mult_interfaces_get_parameters{#1#4:}[\s!parent=#1##2]%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
\fi
\else
+ \the#6% predefine
\let#8\empty
- \mult_interfaces_get_parameters{#1#4:}[\s!parent=#3]%
+ \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
\fi\fi
\the#7%
\let#4#9}}
@@ -298,7 +315,7 @@
\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
+ \unexpanded\def#4[##1][##2]% maybe helper
{\let#7#3%
\ifsecondargument
\def\mult_interfaces_with_comma_list_element####1% we will have a simple one as well
@@ -342,7 +359,7 @@
\newtoks#8%
\newtoks#9%
\ifx#6\relax\let#6\empty\fi
- \def#4[##1][##2]% maybe helper
+ \unexpanded\def#4[##1][##2]% maybe helper
{\ifsecondargument % no commalist here
% \setuplayout[whatever][key=value]
\let#7#3%
@@ -354,7 +371,8 @@
\ifx#3#6\the#8\fi % only switchsetups if previous == current
\let#3#7%
\else\iffirstargument
- \mult_check_for_assignment##1=@@\_end_ % \docheckassignment{##1}%
+ % \mult_check_for_assignment{##1}%
+ \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_
\ifassignment
% \setuplayout[key=value]
\let#7#3%
@@ -413,7 +431,8 @@
\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
+ \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
+ \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
\the#5}%
\processcommalist[##1]\mult_interfaces_with_comma_list_element
\else\ifsecondargument
@@ -486,25 +505,26 @@
%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\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5%
+ {\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
+ \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
+ % \def#4##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
+ \def#5##1{\csname#1##1\endcsname}}
\unexpanded\def\installdirectparameterhandler#1#2%
{\normalexpanded
{\mult_interfaces_install_direct_parameter_handler
{\noexpand#1}%
+ \expandafter\noexpand\csname current#2\endcsname
\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\mult_interfaces_install_direct_setup_handler#1#2#3#4#5%
{\unexpanded\def#2{\dosingleempty#3}%
- \newtoks#4%
- \def#3[##1]%
- {\mult_interfaces_get_parameters#1[##1]%
- \the#4}}
+ \newtoks#5%
+ \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}%
+ \def#4{\mult_interfaces_get_parameters#1}}
\unexpanded\def\installdirectsetuphandler#1#2%
{\normalexpanded
@@ -512,6 +532,7 @@
{\noexpand#1}% \??aa
\expandafter\noexpand\csname setup#2\endcsname
\expandafter\noexpand\csname setup_#2\endcsname % semi-public
+ \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency)
\expandafter\noexpand\csname everysetup#2\endcsname}}
\unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
@@ -578,6 +599,34 @@
\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}}
+%D Here is another experiment:
+
+\unexpanded\def\installactionhandler#1%
+ {\normalexpanded
+ {\mult_interfaces_install_action_handler
+ {#1}%
+ \expandafter\noexpand\csname current#1\endcsname
+ \expandafter\noexpand\csname setupcurrent#1\endcsname
+ \expandafter\noexpand\csname #1_action\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_action_handler#1#2#3#4%
+ {\unexpanded\expandafter\def\csname#1\endcsname{\dodoubleempty#4}%
+ \unexpanded\def#4[##1][##2]%
+ {\begingroup
+ \ifsecondargument
+ \edef#2{##1}%
+ #3[##2]%
+ \else\iffirstargument
+ \doifassignmentelse{##1}
+ {\let#2\empty
+ #3[##1]}%
+ {\edef#2{##1}}%
+ \else
+ \let#2\empty
+ \fi\fi
+ \directsetup{handler:action:#1}%
+ \endgroup}}
+
% First we had, in tune with the regular system variables:
%
% \starttyping
@@ -606,9 +655,7 @@
\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{\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>
@@ -635,6 +682,10 @@
\ctxcommand{registernamespace(\number\c_mult_interfaces_n_of_namespaces,"#1")}%
\fi}
+\def\mult_interfaces_get_parameters_error#1#2#3% redefined
+ {\ctxcommand{showassignerror("#1","#2","#3",\the\inputlineno)}%
+ \waitonfatalerror}
+
% We install two core namespaces here, as we want nice error messages. Maybe
% we will reserve the first 9.
@@ -642,6 +693,34 @@
\installcorenamespace{fontinstancebasic}
\installcorenamespace{fontinstanceclass}
+%D The next one is handy for local assignments.
+
+\installcorenamespace{dummy}
+
+\letvalue\??dummy\empty
+
+ \def\dummyparameter #1{\csname\??dummy\ifcsname\??dummy#1\endcsname#1\fi\endcsname}
+ \def\directdummyparameter#1{\csname\??dummy#1\endcsname}
+\unexpanded\def\setdummyparameter #1{\expandafter\def\csname\??dummy#1\endcsname}
+\unexpanded\def\letdummyparameter #1{\expandafter\let\csname\??dummy#1\endcsname}
+
+% \unexpanded\def\getdummyparameters
+% {\mult_interfaces_get_parameters\??dummy}
+
+\unexpanded\def\getdummyparameters[#1%
+ {\if\noexpand#1]%
+ \expandafter\gobbleoneargument
+ \else
+ \let\m_mult_interfaces_namespace\??dummy
+ \expandafter\mult_interfaces_get_parameters_indeed
+ \fi#1}
+
+\mult_interfaces_install_style_and_color_handler
+ \directdummyparameter
+ \usedummystyleandcolor
+ \usedummystyleparameter
+ \usedummycolorparameter
+
% Maybe a \definecorenamespace[name][directparameter,directsetup][parent]
% but we don't gain much. Actually we might just inline all definitions.
@@ -707,6 +786,31 @@
\expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
\fi}
+%D Another helper:
+
+\unexpanded\def\doifelsecommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doifcommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotcommandhandler#1#2% namespace name
+ {\ifcsname#1#2:\s!parent\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\let\doifcommandhandlerelse\doifelsecommandhandler
+
%D Conventions:
%D
%D \starttyping
diff --git a/tex/context/base/mult-chk.lua b/tex/context/base/mult-chk.lua
index 43e7c5121..e3908ad40 100644
--- a/tex/context/base/mult-chk.lua
+++ b/tex/context/base/mult-chk.lua
@@ -9,9 +9,10 @@ if not modules then modules = { } end modules ['mult-chk'] = {
local format = string.format
local lpegmatch = lpeg.match
local type = type
-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
+local make_settings_to_hash_pattern = utilities.parsers.make_settings_to_hash_pattern
+local settings_to_set = utilities.parsers.settings_to_set
+local allocate = utilities.storage.allocate
local report_interface = logs.reporter("interface","checking")
diff --git a/tex/context/base/mult-chk.mkiv b/tex/context/base/mult-chk.mkiv
index 9260d2040..1d02f166d 100644
--- a/tex/context/base/mult-chk.mkiv
+++ b/tex/context/base/mult-chk.mkiv
@@ -35,8 +35,8 @@
\registerctxluafile{mult-chk}{1.001}
-\def\setvalidparameterkeys{\dodoubleargument\mult_checkers_set_valid_parameter_keys}
-\def\addvalidparameterkeys{\dodoubleargument\mult_checkers_add_valid_parameter_keys}
+\unexpanded\def\setvalidparameterkeys{\dodoubleargument\mult_checkers_set_valid_parameter_keys}
+\unexpanded\def\addvalidparameterkeys{\dodoubleargument\mult_checkers_add_valid_parameter_keys}
\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)}}
@@ -61,12 +61,12 @@
\expandafter\mult_checkers_get_checked_parameters_nop_indeed
\fi{#3}#5}
-\def\mult_checkers_get_checked_parameters_nop_indeed#1#2]%
- {\def\p!dogetparameter{\p!doassign#1}%
- \xprocesscommaitem#2,],\@relax@}
+\def\mult_checkers_get_checked_parameters_nop_indeed#1#2]% needs checking with adapted syst-aux.mkiv
+ {\def\syst_helpers_get_parameters_assign{\syst_helpers_get_parameters_assign_indeed#1}% will change
+ \syst_helpers_process_comma_item#2,],\_e_o_p_}
-\def\disablecheckparameters{\let\getcheckedparameters\mult_checkers_get_checked_parameters_nop}
-\def\enablecheckparameters {\let\getcheckedparameters\mult_checkers_get_checked_parameters_yes}
+\unexpanded\def\disablecheckparameters{\let\getcheckedparameters\mult_checkers_get_checked_parameters_nop}
+\unexpanded\def\enablecheckparameters {\let\getcheckedparameters\mult_checkers_get_checked_parameters_yes}
\disablecheckparameters
diff --git a/tex/context/base/mult-de.mkii b/tex/context/base/mult-de.mkii
index dee614e5e..ce34b6a5b 100644
--- a/tex/context/base/mult-de.mkii
+++ b/tex/context/base/mult-de.mkii
@@ -157,6 +157,7 @@
\setinterfacevariable{enumeration}{nummerierung}
\setinterfacevariable{environment}{umgebung}
\setinterfacevariable{even}{gerade}
+\setinterfacevariable{export}{export}
\setinterfacevariable{external}{extern}
\setinterfacevariable{fact}{gegeben}
\setinterfacevariable{february}{februar}
@@ -455,6 +456,7 @@
\setinterfacevariable{subforward}{untervorwaerts}
\setinterfacevariable{subject}{thema}
\setinterfacevariable{subpage}{unterseite}
+\setinterfacevariable{subs}{subs}
\setinterfacevariable{subsection}{unterabsatz}
\setinterfacevariable{subsubject}{unterthema}
\setinterfacevariable{subsubsection}{unterunterabsatz}
@@ -684,6 +686,7 @@
\setinterfaceconstant{filtercommand}{filtercommand}
\setinterfaceconstant{finalnamesep}{finalnamesep}
\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{firstpage}{ersteseite}
\setinterfaceconstant{focus}{focus}
\setinterfaceconstant{focusin}{focusin}
\setinterfaceconstant{focusout}{focusout}
@@ -750,6 +753,7 @@
\setinterfaceconstant{label}{label}
\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpage}{letzteseite}
\setinterfaceconstant{lastpubsep}{lastpubsep}
\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{links}
@@ -770,6 +774,7 @@
\setinterfaceconstant{leftsubsentence}{linkersubsatz}
\setinterfaceconstant{lefttext}{linkertext}
\setinterfaceconstant{leftwidth}{linkerbreite}
+\setinterfaceconstant{less}{less}
\setinterfaceconstant{level}{niveau}
\setinterfaceconstant{levels}{niveaus}
\setinterfaceconstant{limittext}{limittext}
@@ -808,6 +813,7 @@
\setinterfaceconstant{minheight}{minhoehe}
\setinterfaceconstant{minwidth}{minbreite}
\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{more}{more}
\setinterfaceconstant{n}{n}
\setinterfaceconstant{name}{name}
\setinterfaceconstant{namesep}{namesep}
@@ -962,6 +968,7 @@
\setinterfaceconstant{separator}{seperator}
\setinterfaceconstant{set}{set}
\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{shrink}{shrink}
\setinterfaceconstant{side}{objektabstand}
\setinterfaceconstant{sidealign}{sidealign}
\setinterfaceconstant{sidemethod}{sidemethod}
@@ -970,6 +977,7 @@
\setinterfaceconstant{sign}{zeichen}
\setinterfaceconstant{size}{groesse}
\setinterfaceconstant{small}{klein}
+\setinterfaceconstant{solution}{solution}
\setinterfaceconstant{sort}{sort}
\setinterfaceconstant{sorttype}{sorttype}
\setinterfaceconstant{source}{quelle}
diff --git a/tex/context/base/mult-def.lua b/tex/context/base/mult-def.lua
index 1a4921a28..26b2b8529 100644
--- a/tex/context/base/mult-def.lua
+++ b/tex/context/base/mult-def.lua
@@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['mult-def'] = {
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"
+ license = "see context related readme files",
+ dataonly = true,
}
return {
@@ -6449,6 +6450,18 @@ return {
},
},
["constants"]={
+ ["less"]={
+ ["en"]="less",
+ ["nl"]="minder",
+ },
+ ["more"]={
+ ["en"]="more",
+ ["nl"]="meer",
+ },
+ ["solution"]={
+ ["en"]="solution",
+ ["nl"]="oplossing",
+ },
["anchor"]={
["en"]="anchor",
["nl"]="anker",
@@ -7805,6 +7818,16 @@ return {
["pe"]="تمرکز",
["ro"]="focus",
},
+ ["firstpage"]={
+ ["cs"]="prvnistranka",
+ ["de"]="ersteseite",
+ ["en"]="firstpage",
+ ["fr"]="premierepage",
+ ["it"]="primapagina",
+ ["nl"]="eerstepagina",
+ ["pe"]="صفحه‌اول",
+ ["ro"]="primapagina",
+ },
["focusin"]={
["cs"]="focusin",
["de"]="focusin",
@@ -8362,6 +8385,16 @@ return {
["pe"]="برچسب",
["ro"]="eticheta",
},
+ ["lastpage"]={
+ ["cs"]="poslednistrana",
+ ["de"]="letzteseite",
+ ["en"]="lastpage",
+ ["fr"]="dernierepage",
+ ["it"]="ultimapagina",
+ ["nl"]="laatstepagina",
+ ["pe"]="صفحه‌آخر",
+ ["ro"]="ultimapagina",
+ },
["left"]={
["cs"]="vlevo",
["de"]="links",
@@ -10023,6 +10056,10 @@ return {
["pe"]="بارگذاریها",
["ro"]="setups",
},
+ ["shrink"]={
+ ["en"]="shrink",
+ ["nl"]="krimp",
+ },
["side"]={
["cs"]="pocitat",
["de"]="objektabstand",
@@ -11277,6 +11314,9 @@ return {
["en"]="end",
["nl"]="eind",
},
+ ["export"] = {
+ ["en"]="export",
+ },
["begin"]={
["en"]="begin",
["nl"]="begin",
@@ -15721,6 +15761,9 @@ return {
["pe"]="زیرصفحه",
["ro"]="subpagina",
},
+ ["subs"]={
+ ["en"]="subs",
+ },
["subsection"]={
["cs"]="podsekce",
["de"]="unterabsatz",
diff --git a/tex/context/base/mult-def.mkiv b/tex/context/base/mult-def.mkiv
index f6f50ae72..0ee59d8c3 100644
--- a/tex/context/base/mult-def.mkiv
+++ b/tex/context/base/mult-def.mkiv
@@ -13,21 +13,75 @@
\unprotect
-\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\??mi:\currentinterface\endcsname\csname\??mi:\currentinterface\endcsname\else en\fi}
-\def\userresponsestag{\ifcsname\??mi:\currentresponses\endcsname\csname\??mi:\currentresponses\endcsname\else en\fi}
+\installcorenamespace{multilingual}
+
+\setvalue{\??multilingual czech}{cs}
+\setvalue{\??multilingual german}{de}
+\setvalue{\??multilingual english}{en}
+\setvalue{\??multilingual french}{fr}
+\setvalue{\??multilingual italian}{it}
+\setvalue{\??multilingual dutch}{nl}
+\setvalue{\??multilingual persian}{pe}
+\setvalue{\??multilingual romanian}{ro}
+
+\def\userinterfacetag{\ifcsname\??multilingual\currentinterface\endcsname\csname\??multilingual\currentinterface\endcsname\else en\fi}
+\def\userresponsestag{\ifcsname\??multilingual\currentresponses\endcsname\csname\??multilingual\currentresponses\endcsname\else en\fi}
% \input mult-\userinterfacetag \relax
% \input mult-m\userresponsestag \relax
\ctxlua{interfaces.setuserinterface("\userinterfacetag","\userresponsestag")}
+% start todo:
+
+\def\c!language {language}
+\def\c!compressseparator{compressseparator}
+\def\c!renderingsetup {renderingsetup}
+\def\c!filler {filler}
+\def\c!resources {resources}
+\def\c!first {first}
+\def\c!last {last}
+\def\c!quotechar {quotechar}
+\def\c!commentchar {commentchar}
+\def\c!symbolcommand {symbolcommand}
+\def\c!xmlsetup {xmlsetup}
+\def\c!comma {comma}
+\def\c!period {period}
+\def\c!monthconversion {monthconversion}
+\def\c!comment {comment}
+\def\c!textalign {textalign}
+\def\c!up {up}
+\def\c!down {down}
+
+\def\v!compressseparator{compressseparator}
+\def\v!notation {notation}
+\def\v!endnote {endnote}
+\def\v!interactive {interactive}
+\def\v!autopunctuation {autopunctuation}
+\def\v!integral {integral}
+\def\v!shiftup {shiftup}
+\def\v!shiftdown {shiftdown}
+\def\v!construction {construction}
+\def\v!unframed {unframed}
+\def\v!chemical {chemical}
+\def\v!chemicals {chemicals}
+
+\def\s!lcgreek {lcgreek}
+\def\s!ucgreek {ucgreek}
+\def\s!italics {italics}
+\def\s!integral {integral}
+\def\s!insert {insert} % maybe insertclass
+
+\def\c!HL {HL}
+\def\c!VL {VL}
+\def\c!NL {NL}
+
+\ifdefined\v!kerncharacters\else \def\v!kerncharacters{kerncharacters} \fi % no time now for translations should be a e! actually
+\ifdefined\v!stretched \else \def\v!stretched {stretched} \fi
+\ifdefined\v!vulgarfraction\else \def\v!vulgarfraction{vulgarfraction} \fi
+\ifdefined\v!block \else \def\v!block {block} \fi
+\ifdefined\v!rule \else \def\v!rule {rule} \fi
+
+% stop todo
+
\protect \endinput
diff --git a/tex/context/base/mult-dim.mkvi b/tex/context/base/mult-dim.mkvi
index 0889b411e..bad7af713 100644
--- a/tex/context/base/mult-dim.mkvi
+++ b/tex/context/base/mult-dim.mkvi
@@ -35,6 +35,7 @@
\installcorenamespace{dimensionnormal}
\setvalue{\??dimensionnormal \v!none }#value#dimension#small#medium#big{#dimension\zeropoint}
+\setvalue{\??dimensionnormal \empty }#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}
diff --git a/tex/context/base/mult-en.mkii b/tex/context/base/mult-en.mkii
index b801ebc5f..860060247 100644
--- a/tex/context/base/mult-en.mkii
+++ b/tex/context/base/mult-en.mkii
@@ -157,6 +157,7 @@
\setinterfacevariable{enumeration}{enumeration}
\setinterfacevariable{environment}{environment}
\setinterfacevariable{even}{even}
+\setinterfacevariable{export}{export}
\setinterfacevariable{external}{external}
\setinterfacevariable{fact}{fact}
\setinterfacevariable{february}{february}
@@ -455,6 +456,7 @@
\setinterfacevariable{subforward}{subforward}
\setinterfacevariable{subject}{subject}
\setinterfacevariable{subpage}{subpage}
+\setinterfacevariable{subs}{subs}
\setinterfacevariable{subsection}{subsection}
\setinterfacevariable{subsubject}{subsubject}
\setinterfacevariable{subsubsection}{subsubsection}
@@ -684,6 +686,7 @@
\setinterfaceconstant{filtercommand}{filtercommand}
\setinterfaceconstant{finalnamesep}{finalnamesep}
\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{firstpage}{firstpage}
\setinterfaceconstant{focus}{focus}
\setinterfaceconstant{focusin}{focusin}
\setinterfaceconstant{focusout}{focusout}
@@ -750,6 +753,7 @@
\setinterfaceconstant{label}{label}
\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpage}{lastpage}
\setinterfaceconstant{lastpubsep}{lastpubsep}
\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{left}
@@ -770,6 +774,7 @@
\setinterfaceconstant{leftsubsentence}{leftsubsentence}
\setinterfaceconstant{lefttext}{lefttext}
\setinterfaceconstant{leftwidth}{leftwidth}
+\setinterfaceconstant{less}{less}
\setinterfaceconstant{level}{level}
\setinterfaceconstant{levels}{levels}
\setinterfaceconstant{limittext}{limittext}
@@ -808,6 +813,7 @@
\setinterfaceconstant{minheight}{minheight}
\setinterfaceconstant{minwidth}{minwidth}
\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{more}{more}
\setinterfaceconstant{n}{n}
\setinterfaceconstant{name}{name}
\setinterfaceconstant{namesep}{namesep}
@@ -962,6 +968,7 @@
\setinterfaceconstant{separator}{separator}
\setinterfaceconstant{set}{set}
\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{shrink}{shrink}
\setinterfaceconstant{side}{side}
\setinterfaceconstant{sidealign}{sidealign}
\setinterfaceconstant{sidemethod}{sidemethod}
@@ -970,6 +977,7 @@
\setinterfaceconstant{sign}{sign}
\setinterfaceconstant{size}{size}
\setinterfaceconstant{small}{small}
+\setinterfaceconstant{solution}{solution}
\setinterfaceconstant{sort}{sort}
\setinterfaceconstant{sorttype}{sorttype}
\setinterfaceconstant{source}{source}
diff --git a/tex/context/base/mult-fr.mkii b/tex/context/base/mult-fr.mkii
index 5717cf97b..f52a761d2 100644
--- a/tex/context/base/mult-fr.mkii
+++ b/tex/context/base/mult-fr.mkii
@@ -157,6 +157,7 @@
\setinterfacevariable{enumeration}{enumeration}
\setinterfacevariable{environment}{environement}
\setinterfacevariable{even}{paire}
+\setinterfacevariable{export}{export}
\setinterfacevariable{external}{external}
\setinterfacevariable{fact}{fait}
\setinterfacevariable{february}{fevrier}
@@ -455,6 +456,7 @@
\setinterfacevariable{subforward}{sousavance}
\setinterfacevariable{subject}{sujet}
\setinterfacevariable{subpage}{souspage}
+\setinterfacevariable{subs}{subs}
\setinterfacevariable{subsection}{soussection}
\setinterfacevariable{subsubject}{soussujet}
\setinterfacevariable{subsubsection}{soussoussection}
@@ -684,6 +686,7 @@
\setinterfaceconstant{filtercommand}{filtercommand}
\setinterfaceconstant{finalnamesep}{finalnamesep}
\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{firstpage}{premierepage}
\setinterfaceconstant{focus}{focus}
\setinterfaceconstant{focusin}{focusin}
\setinterfaceconstant{focusout}{focusout}
@@ -750,6 +753,7 @@
\setinterfaceconstant{label}{etiquette}
\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpage}{dernierepage}
\setinterfaceconstant{lastpubsep}{lastpubsep}
\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{gauche}
@@ -770,6 +774,7 @@
\setinterfaceconstant{leftsubsentence}{sousphrasegauche}
\setinterfaceconstant{lefttext}{textegauche}
\setinterfaceconstant{leftwidth}{largeurgauche}
+\setinterfaceconstant{less}{less}
\setinterfaceconstant{level}{niveau}
\setinterfaceconstant{levels}{niveaux}
\setinterfaceconstant{limittext}{limittext}
@@ -808,6 +813,7 @@
\setinterfaceconstant{minheight}{hauteurmin}
\setinterfaceconstant{minwidth}{largeurmin}
\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{more}{more}
\setinterfaceconstant{n}{n}
\setinterfaceconstant{name}{nom}
\setinterfaceconstant{namesep}{namesep}
@@ -962,6 +968,7 @@
\setinterfaceconstant{separator}{separateur}
\setinterfaceconstant{set}{set}
\setinterfaceconstant{setups}{reglages}
+\setinterfaceconstant{shrink}{shrink}
\setinterfaceconstant{side}{cote}
\setinterfaceconstant{sidealign}{sidealign}
\setinterfaceconstant{sidemethod}{sidemethod}
@@ -970,6 +977,7 @@
\setinterfaceconstant{sign}{signe}
\setinterfaceconstant{size}{dimension}
\setinterfaceconstant{small}{petit}
+\setinterfaceconstant{solution}{solution}
\setinterfaceconstant{sort}{sort}
\setinterfaceconstant{sorttype}{sorttype}
\setinterfaceconstant{source}{origine}
diff --git a/tex/context/base/mult-fun.lua b/tex/context/base/mult-fun.lua
new file mode 100644
index 000000000..ab9c5d434
--- /dev/null
+++ b/tex/context/base/mult-fun.lua
@@ -0,0 +1,95 @@
+return {
+ internals = {
+ --
+ "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel",
+ "shadefactor",
+ "textextoffset",
+ "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent",
+ "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent",
+ "differencetransparent", "exclusiontransparent", "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent",
+-- "originlength", "tickstep ", "ticklength",
+-- "autoarrows", "ahfactor",
+-- "angleoffset", anglelength", anglemethod",
+ },
+ 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",
+ -- "halfcircle", "quartercircle",
+ "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", "autoalign",
+ "transparent", "withtransparency",
+ "asgroup",
+ "infont", -- redefined usign textext
+ -- "property", "withproperties", "properties", -- not yet
+ "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", -- redefined
+ "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",
+-- "colorlike", "dowithpath", "rangepath", "straightpath", "addbackground",
+-- "cleanstring", "asciistring", "setunstringed", "getunstringed", "unstringed",
+-- "showgrid",
+-- "phantom",
+-- "xshifted", "yshifted",
+-- "drawarrowpath", "midarrowhead", "arrowheadonpath",
+-- "drawxticks", "drawyticks", "drawticks",
+-- "pointarrow",
+-- "thefreelabel", "freelabel", "freedotlabel",
+-- "anglebetween", "colorcircle",
+-- "remapcolors", "normalcolors", "resetcolormap", "remapcolor", "remappedcolor",
+-- "recolor", "refill", "redraw", "retext", "untext", "restroke", "reprocess", "repathed",
+ "tensecircle", "roundedsquare",
+ "colortype", "whitecolor", "blackcolor",
+ --
+-- "swappointlabels",
+ "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/tex/context/base/mult-ini.lua b/tex/context/base/mult-ini.lua
index d14f38ad5..59eed7d83 100644
--- a/tex/context/base/mult-ini.lua
+++ b/tex/context/base/mult-ini.lua
@@ -6,16 +6,17 @@ if not modules then modules = { } end modules ['mult-ini'] = {
license = "see context related readme files"
}
-local format, gmatch, gsub = string.format, string.gmatch, string.gsub
+local format, gmatch, gsub, match = string.format, string.gmatch, string.gsub, string.match
local lpegmatch = lpeg.match
local serialize = table.serialize
-local allocate = utilities.storage.allocate
-local mark = utilities.storage.mark
-local contextsprint = context.sprint
-local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local mark = utilities.storage.mark
+local prtcatcodes = catcodes.numbers.prtcatcodes
+local contextsprint = context.sprint
+local setmetatableindex = table.setmetatableindex
-local report_interface = logs.reporter("interface","initialization")
+local report_interface = logs.reporter("interface","initialization")
interfaces = interfaces or { }
interfaces.constants = mark(interfaces.constants or { })
@@ -25,27 +26,38 @@ 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")
+local registerstorage = storage.register
+local sharedstorage = storage.shared
+
+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
+
+registerstorage("interfaces/constants", constants, "interfaces.constants")
+registerstorage("interfaces/variables", variables, "interfaces.variables")
+registerstorage("interfaces/elements", elements, "interfaces.elements")
+registerstorage("interfaces/formats", formats, "interfaces.formats")
+registerstorage("interfaces/translations", translations, "interfaces.translations")
+registerstorage("interfaces/corenamespaces", corenamespaces, "interfaces.corenamespaces")
interfaces.interfaces = {
"cs", "de", "en", "fr", "it", "nl", "ro", "pe",
}
-storage.shared.currentinterface = storage.shared.currentinterface or "en"
-storage.shared.currentresponse = storage.shared.currentresponse or "en"
+sharedstorage.currentinterface = sharedstorage.currentinterface or "en"
+sharedstorage.currentresponse = sharedstorage.currentresponse or "en"
-local currentinterface = storage.shared.currentinterface
-local currentresponse = storage.shared.currentresponse
+local currentinterface = sharedstorage.currentinterface
+local currentresponse = sharedstorage.currentresponse
local complete = allocate()
interfaces.complete = complete
-local function resolve(t,k) -- one access needed to get loaded
+local function resolve(t,k) -- one access needed to get loaded (not stored!)
report_interface("loading interface definitions from 'mult-def.lua'")
complete = dofile(resolvers.findfile("mult-def.lua"))
report_interface("loading interface messages from 'mult-mes.lua'")
@@ -56,14 +68,6 @@ 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 corenamespaces = interfaces.corenamespaces
-local reporters = { } -- just an optimization
-
local function valueiskey(t,k) -- will be helper
t[k] = k
return k
@@ -75,7 +79,7 @@ setmetatableindex(elements, valueiskey)
setmetatableindex(formats, valueiskey)
setmetatableindex(translations, valueiskey)
-function commands.registernamespace(n,namespace)
+function interfaces.registernamespace(n,namespace)
corenamespaces[n] = namespace
end
@@ -85,7 +89,7 @@ local function resolve(t,k)
return v
end
-setmetatableindex(reporters, resolve)
+setmetatableindex(reporters,resolve)
for category, _ in next, translations do
-- We pre-create reporters for already defined messages
@@ -146,7 +150,7 @@ function interfaces.getmessage(category,tag,default)
end
function interfaces.doifelsemessage(category,tag)
- return commands.testcase(formats[fulltag(category,tag)])
+ return formats[fulltag(category,tag)]
end
local splitter = lpeg.splitat(",")
@@ -184,45 +188,38 @@ end
logs.setmessenger(context.verbatim.ctxreport)
--- status
-
-function commands.writestatus(category,message,...)
- local r = reporters[category]
- r(message,...)
-end
-
-- initialization
function interfaces.setuserinterface(interface,response)
- storage.shared.currentinterface, currentinterface = interface, interface
- storage.shared.currentresponse, currentresponse = response, response
+ sharedstorage.currentinterface, currentinterface = interface, interface
+ sharedstorage.currentresponse, currentresponse = response, response
if environment.initex then
local nofconstants = 0
for given, constant in next, complete.constants do
constant = constant[interface] or constant.en or given
constants[constant] = given -- breedte -> width
- contextsprint("\\do@sicon{",given,"}{",constant,"}")
+ contextsprint(prtcatcodes,"\\ui_c{",given,"}{",constant,"}") -- user interface 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
- contextsprint("\\do@sivar{",given,"}{",variable,"}")
+ contextsprint(prtcatcodes,"\\ui_v{",given,"}{",variable,"}") -- user interface 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
- contextsprint("\\do@siele{",given,"}{",element,"}")
+ contextsprint(prtcatcodes,"\\ui_e{",given,"}{",element,"}") -- user interface 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
- contextsprint("\\do@sicom{",given,"}{",command,"}")
+ contextsprint(prtcatcodes,"\\ui_m{",given,"}{",command,"}") -- user interface macro
end
nofcommands = nofcommands + 1
end
@@ -244,12 +241,12 @@ end
interfaces.cachedsetups = interfaces.cachedsetups or { }
interfaces.hashedsetups = interfaces.hashedsetups or { }
-storage.register("interfaces/cachedsetups", interfaces.cachedsetups, "interfaces.cachedsetups")
-storage.register("interfaces/hashedsetups", interfaces.hashedsetups, "interfaces.hashedsetups")
-
local cachedsetups = interfaces.cachedsetups
local hashedsetups = interfaces.hashedsetups
+storage.register("interfaces/cachedsetups", cachedsetups, "interfaces.cachedsetups")
+storage.register("interfaces/hashedsetups", hashedsetups, "interfaces.hashedsetups")
+
function interfaces.cachesetup(t)
local hash = serialize(t)
local done = hashedsetups[hash]
@@ -271,3 +268,40 @@ function interfaces.interfacedcommand(name)
local command = complete.commands[name]
return command and command[currentinterface] or name
end
+
+-- interface
+
+function commands.writestatus(category,message,...)
+ local r = reporters[category]
+ if r then
+ r(message,...)
+ end
+end
+
+commands.registernamespace = interfaces.registernamespace
+commands.setinterfaceconstant = interfaces.setconstant
+commands.setinterfacevariable = interfaces.setvariable
+commands.setinterfaceelement = interfaces.setelement
+commands.setinterfacemessage = interfaces.setmessage
+commands.setinterfacemessages = interfaces.setmessages
+commands.showmessage = interfaces.showmessage
+
+function commands.doifelsemessage(category,tag)
+ commands.doifelse(interfaces.doifelsemessage(category,tag))
+end
+
+function commands.getmessage(category,tag,default)
+ context(interfaces.getmessage(category,tag,default))
+end
+
+function commands.showassignerror(namespace,key,value,line)
+ local ns, instance = match(namespace,"^(%d+)[^%a]+(%a+)")
+ if ns then
+ namespace = corenamespaces[tonumber(ns)] or ns
+ end
+ if instance then
+ context.writestatus("setup",format("error in line %s, namespace %q, instance %q, key %q",line,namespace,instance,key))
+ else
+ context.writestatus("setup",format("error in line %s, namespace %q, key %q",line,namespace,key))
+ end
+end
diff --git a/tex/context/base/mult-ini.mkiv b/tex/context/base/mult-ini.mkiv
index f0d47103d..eb5517277 100644
--- a/tex/context/base/mult-ini.mkiv
+++ b/tex/context/base/mult-ini.mkiv
@@ -101,24 +101,27 @@
%D
%D \starttyping
%D \hrule width 10pt height 2pt depth 1pt
-%D \hrule \!!width 10pt \!!height 2pt \!!depth 1pt
+%D \hrule \s!width 10pt \s!height 2pt \s!depth 1pt
%D \stoptyping
%D
-%D One condition is that we have defined \type{\!!height},
-%D \type{\!!width} and \type{\!!depth} as respectively
-%D \type{height}, \type{width} and \type{depth}. Using this
+%D One condition is that we have defined \type {\s!height},
+%D \type {\s!width} and \type {\s!depth} as respectively
+%D \type {height}, \type {width} and \type {depth}. Using this
%D scheme therefore only makes sense when a token sequence is
%D used more than once. Savings like this should of course be
%D implemented in english, just because \TEX\ is english.
-\def\!!width {width}
-\def\!!height{height}
-\def\!!depth {depth}
-\def\!!plus {plus}
-\def\!!minus {minus}
-\def\!!fill {fill}
-\def\!!to {to}
-\def\!!spread{spread}
+\def\s!width {width} \let\!!width \s!width % obsolete
+\def\s!height{height} \let\!!height\s!height % obsolete
+\def\s!depth {depth} \let\!!depth \s!depth % obsolete
+\def\s!spread{spread} \let\!!spread\s!spread % obsolete
+\def\s!plus {plus} \let\!!plus \s!plus % obsolete
+\def\s!minus {minus} \let\!!minus \s!minus % obsolete
+\def\s!fil {fil}
+\def\s!fill {fill} \let\!!fill \s!fill % obsolete
+\def\s!filll {filll}
+\def\s!to {to} \let\!!to \s!to % obsolete
+\def\s!attr {attr}
%D Kind of special:
@@ -361,7 +364,7 @@
\doifinsetelse{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}}
\def\mult_messages_start_yes#1#2\stopmessages
- {\ctxlua{interfaces.setmessages("#1",\!!bs#2\!!es)}%
+ {\ctxcommand{setinterfacemessages("#1",\!!bs#2\!!es)}%
\egroup}
\def\mult_messages_start_nop#1#2\stopmessages
@@ -371,12 +374,12 @@
\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)}}
+ \ctxcommand{setinterfacemessage("#1","#2",\!!bs#3\!!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\setmessagetext #1#2{\edef\currentmessagetext{\ctxcommand{getmessage("#1","#2")}}}
+\unexpanded\def\getmessage #1#2{\ctxcommand{getmessage("#1","#2")}}
+\unexpanded\def\doifelsemessage #1#2{\ctxcommand{doifelsemessage("#1","#2")}}
+\unexpanded\def\showmessage #1#2#3{\ctxcommand{showmessage("#1","#2",\!!bs#3\!!es)}}
\unexpanded\def\writestatus #1#2{\ctxcommand{writestatus("#1",\!!bs#2\!!es)}}
%D \macros
@@ -723,11 +726,11 @@
% temporary mkiv hack (we can best just store the whole table in memory)
\unexpanded\def\setinterfaceconstant#1#2%
- {\ctxlua{interfaces.setconstant("#1","#2")}%
+ {\ctxcommand{setinterfaceconstant("#1","#2")}%
\expandafter\def\csname\c!prefix!#1\endcsname{#1}}
\unexpanded\def\setinterfacevariable#1#2%
- {\ctxlua{interfaces.setvariable("#1","#2")}%
+ {\ctxcommand{setinterfacevariable("#1","#2")}%
\expandafter\def\csname\v!prefix!#1\endcsname{#2}}
%D \macros
@@ -756,7 +759,7 @@
%D part is needed, we use a \type{-}:
\unexpanded\def\setinterfaceelement#1#2%
- {\ctxlua{interfaces.setelement("#1","#2")}%
+ {\ctxcommand{setinterfaceelement("#1","#2")}%
\ifcsname\e!prefix!#1\endcsname
\doifnotvalue{\e!prefix!#1}{#2}{\setvalue{\e!prefix!#1}{#2}}%
\else
@@ -776,15 +779,27 @@
%D For at the \LUA\ end (experiment):
-\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}}
+% \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}}
+%
+% \startinterface english
+%
+% \def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
+%
+% \stopinterface
+
+\def\ui_c#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}%
+ \expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english
+\def\ui_v#1#2{\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}}
+\def\ui_e#1#2{\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}}
+\def\ui_m#1#2{\expandafter\gdef\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}
\startinterface english
- \def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
+ \def\ui_c#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
\stopinterface
@@ -814,7 +829,8 @@
\def\contextversion {unknown}
\def\contextversionnumber{0}
\else
- \def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3 #4:#5}
+ %\def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi#2\ifnum#3<10 0\fi#3 #4:#5}
+ \def\contextversionnumber#1.#2.#3 #4:#5\relax{#1\ifnum#2<10 0\fi\purenumber{#2}\ifnum#3<10 0\fi\purenumber{#3} #4:#5}
\edef\contextversionnumber{\expandafter\contextversionnumber\contextversion\relax\space\contextmark}
\fi
diff --git a/tex/context/base/mult-it.mkii b/tex/context/base/mult-it.mkii
index 88a371ac7..b91e3ee5b 100644
--- a/tex/context/base/mult-it.mkii
+++ b/tex/context/base/mult-it.mkii
@@ -157,6 +157,7 @@
\setinterfacevariable{enumeration}{enumerazione}
\setinterfacevariable{environment}{ambiente}
\setinterfacevariable{even}{pari}
+\setinterfacevariable{export}{export}
\setinterfacevariable{external}{esterno}
\setinterfacevariable{fact}{fatto}
\setinterfacevariable{february}{febbraio}
@@ -455,6 +456,7 @@
\setinterfacevariable{subforward}{sottoavanti}
\setinterfacevariable{subject}{argomento}
\setinterfacevariable{subpage}{sottopagina}
+\setinterfacevariable{subs}{subs}
\setinterfacevariable{subsection}{sottocapoverso}
\setinterfacevariable{subsubject}{sottoargomento}
\setinterfacevariable{subsubsection}{sottosottocapoverso}
@@ -684,6 +686,7 @@
\setinterfaceconstant{filtercommand}{filtercommand}
\setinterfaceconstant{finalnamesep}{finalnamesep}
\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{firstpage}{primapagina}
\setinterfaceconstant{focus}{focus}
\setinterfaceconstant{focusin}{focusin}
\setinterfaceconstant{focusout}{focusout}
@@ -750,6 +753,7 @@
\setinterfaceconstant{label}{etichetta}
\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpage}{ultimapagina}
\setinterfaceconstant{lastpubsep}{lastpubsep}
\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{sinistra}
@@ -770,6 +774,7 @@
\setinterfaceconstant{leftsubsentence}{sottofrasesinistra}
\setinterfaceconstant{lefttext}{testosinistro}
\setinterfaceconstant{leftwidth}{ampiezzasinistra}
+\setinterfaceconstant{less}{less}
\setinterfaceconstant{level}{livello}
\setinterfaceconstant{levels}{livelli}
\setinterfaceconstant{limittext}{limittext}
@@ -808,6 +813,7 @@
\setinterfaceconstant{minheight}{altezzamin}
\setinterfaceconstant{minwidth}{ampiezzamin}
\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{more}{more}
\setinterfaceconstant{n}{n}
\setinterfaceconstant{name}{nome}
\setinterfaceconstant{namesep}{namesep}
@@ -962,6 +968,7 @@
\setinterfaceconstant{separator}{separatore}
\setinterfaceconstant{set}{set}
\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{shrink}{shrink}
\setinterfaceconstant{side}{lato}
\setinterfaceconstant{sidealign}{sidealign}
\setinterfaceconstant{sidemethod}{sidemethod}
@@ -970,6 +977,7 @@
\setinterfaceconstant{sign}{segno}
\setinterfaceconstant{size}{dimensione}
\setinterfaceconstant{small}{piccolo}
+\setinterfaceconstant{solution}{solution}
\setinterfaceconstant{sort}{sort}
\setinterfaceconstant{sorttype}{sorttype}
\setinterfaceconstant{source}{origine}
diff --git a/tex/context/base/mult-low.lua b/tex/context/base/mult-low.lua
index 7d61d0427..bffdd288f 100644
--- a/tex/context/base/mult-low.lua
+++ b/tex/context/base/mult-low.lua
@@ -17,6 +17,7 @@ return {
"zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint",
"points", "halfpoint",
"zeroskip",
+ "zeromuskip", "onemuskip",
"pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi",
"normalpagebox",
-- --
@@ -122,8 +123,10 @@ return {
"startlocalsetups", "stoplocalsetups",
"starttexdefinition", "stoptexdefinition",
"starttexcode", "stoptexcode",
+ "startcontextcode", "stopcontextcode",
--
"doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup",
+ "doifelsecommandhandler","doifnotcommandhandler","doifcommandhandler",
--
"newmode", "setmode", "resetmode",
"newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode",
@@ -134,13 +137,22 @@ return {
--
"then",
--
- "donothing", "dontcomplain",
+ "firstargumentfalse", "firstargumenttrue",
+ "secondargumentfalse", "secondargumenttrue",
+ "thirdargumentfalse", "thirdargumenttrue",
+ "fourthargumentfalse", "fourthargumenttrue",
+ "fifthargumentfalse", "fifthsargumenttrue",
+ "sixthargumentfalse", "sixtsargumenttrue",
+ --
+ "doglobal", "dodoglobal", "redoglobal", "resetglobal",
+ --
+ "donothing", "dontcomplain", "forgetall",
--
"donetrue", "donefalse",
--
"htdp",
"unvoidbox",
- "vfilll",
+ "hfilll", "vfilll",
--
"mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha",
--
@@ -165,10 +177,15 @@ return {
"scratchtoks", "globalscratchtoks",
"scratchbox", "globalscratchbox",
--
+ "availablehsize", "localhsize", "setlocalhsize",
+ --
"nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs",
--
"scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance",
"scratchhsize", "scratchvsize",
+ "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset",
+ "scratchxposition", "scratchyposition",
+ "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset",
--
"scratchcounterone", "scratchcountertwo", "scratchcounterthree",
"scratchdimenone", "scratchdimentwo", "scratchdimenthree",
@@ -176,6 +193,9 @@ return {
"scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree",
"scratchtoksone", "scratchtokstwo", "scratchtoksthree",
"scratchboxone", "scratchboxtwo", "scratchboxthree",
+ "scratchnx", "scratchny", "scratchmx", "scratchmy",
+ --
+ "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip",
--
"doif", "doifnot", "doifelse",
"doifinset", "doifnotinset", "doifinsetelse",
@@ -184,33 +204,38 @@ return {
"doifelsevalue", "doifvalue", "doifnotvalue",
"doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse",
"doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing",
- "doifdimensionelse", "doifnumberelse",
+ "doifdimensionelse", "doifnumberelse", "doifnumber", "doifnotnumber",
"doifcommonelse", "doifcommon", "doifnotcommon",
"doifinstring", "doifnotinstring", "doifinstringelse",
- "doifassignmentelse",
+ "doifassignmentelse", "docheckassignment",
--
"tracingall", "tracingnone", "loggingall",
--
- "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to",
+ "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to",
--
- "endgraf", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace",
+ "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace",
--
"executeifdefined",
--
"singleexpandafter", "doubleexpandafter", "tripleexpandafter",
--
- "dontleavehmode", "removelastspace", "removeunwantedspaces",
+ "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces",
--
"wait", "writestatus", "define", "redefine",
--
- "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "measure",
+ "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure",
--
"getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue",
"resetvalue", "undefinevalue", "ignorevalue",
"setuvalue", "setuevalue", "setugvalue", "setuxvalue",
- "globallet", "glet",
+ --
+ "globallet", "glet", "udef", "ugdef", "uedef", "uxdef",
+ --
"getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters",
--
+ "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter",
+ "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter",
+ --
"processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist",
"processaction", "processallactions", "processfirstactioninset", "processallactionsinset",
--
@@ -232,9 +257,10 @@ return {
--
"newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant",
"newmacro", "setnewmacro", "newfraction",
+ "newsignal",
--
"dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty",
- "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument",
+ "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument",
"dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty",
--
"nopdfcompression", "maximumpdfcompression", "normalpdfcompression",
@@ -245,6 +271,8 @@ return {
--
"startnointerference", "stopnointerference",
--
- "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "begstrut", "endstrut",
+ "twodigits","threedigits",
+ --
+ "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight",
}
}
diff --git a/tex/context/base/mult-mes.lua b/tex/context/base/mult-mes.lua
index 473c86d35..68a392190 100644
--- a/tex/context/base/mult-mes.lua
+++ b/tex/context/base/mult-mes.lua
@@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['mult-mes'] = {
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"
+ license = "see context related readme files",
+ dataonly = true,
}
-- floatsblocks -> floats
diff --git a/tex/context/base/mult-nl.mkii b/tex/context/base/mult-nl.mkii
index 01f7fa204..dbce41d85 100644
--- a/tex/context/base/mult-nl.mkii
+++ b/tex/context/base/mult-nl.mkii
@@ -157,6 +157,7 @@
\setinterfacevariable{enumeration}{doornummering}
\setinterfacevariable{environment}{omgeving}
\setinterfacevariable{even}{even}
+\setinterfacevariable{export}{export}
\setinterfacevariable{external}{extern}
\setinterfacevariable{fact}{gegeven}
\setinterfacevariable{february}{februari}
@@ -455,6 +456,7 @@
\setinterfacevariable{subforward}{subvooruit}
\setinterfacevariable{subject}{onderwerp}
\setinterfacevariable{subpage}{subpagina}
+\setinterfacevariable{subs}{subs}
\setinterfacevariable{subsection}{subparagraaf}
\setinterfacevariable{subsubject}{subonderwerp}
\setinterfacevariable{subsubsection}{subsubparagraaf}
@@ -684,6 +686,7 @@
\setinterfaceconstant{filtercommand}{filtercommand}
\setinterfaceconstant{finalnamesep}{finalnamesep}
\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{firstpage}{eerstepagina}
\setinterfaceconstant{focus}{focus}
\setinterfaceconstant{focusin}{focusin}
\setinterfaceconstant{focusout}{focusuit}
@@ -750,6 +753,7 @@
\setinterfaceconstant{label}{label}
\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpage}{laatstepagina}
\setinterfaceconstant{lastpubsep}{lastpubsep}
\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{links}
@@ -770,6 +774,7 @@
\setinterfaceconstant{leftsubsentence}{linkersubzin}
\setinterfaceconstant{lefttext}{linkertekst}
\setinterfaceconstant{leftwidth}{linkerbreedte}
+\setinterfaceconstant{less}{minder}
\setinterfaceconstant{level}{niveau}
\setinterfaceconstant{levels}{niveaus}
\setinterfaceconstant{limittext}{limiettekst}
@@ -808,6 +813,7 @@
\setinterfaceconstant{minheight}{minhoogte}
\setinterfaceconstant{minwidth}{minbreedte}
\setinterfaceconstant{monthconversion}{maandconversie}
+\setinterfaceconstant{more}{meer}
\setinterfaceconstant{n}{n}
\setinterfaceconstant{name}{naam}
\setinterfaceconstant{namesep}{namesep}
@@ -962,6 +968,7 @@
\setinterfaceconstant{separator}{scheider}
\setinterfaceconstant{set}{set}
\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{shrink}{krimp}
\setinterfaceconstant{side}{zij}
\setinterfaceconstant{sidealign}{zijuitlijnen}
\setinterfaceconstant{sidemethod}{zijmethode}
@@ -970,6 +977,7 @@
\setinterfaceconstant{sign}{teken}
\setinterfaceconstant{size}{formaat}
\setinterfaceconstant{small}{klein}
+\setinterfaceconstant{solution}{oplossing}
\setinterfaceconstant{sort}{sort}
\setinterfaceconstant{sorttype}{sortering}
\setinterfaceconstant{source}{bron}
diff --git a/tex/context/base/mult-pe.mkii b/tex/context/base/mult-pe.mkii
index 6dcd2fef6..58d3ff527 100644
--- a/tex/context/base/mult-pe.mkii
+++ b/tex/context/base/mult-pe.mkii
@@ -157,6 +157,7 @@
\setinterfacevariable{enumeration}{شماره‌بندی}
\setinterfacevariable{environment}{محیط}
\setinterfacevariable{even}{زوج}
+\setinterfacevariable{export}{export}
\setinterfacevariable{external}{خارجی}
\setinterfacevariable{fact}{fact}
\setinterfacevariable{february}{فوریه}
@@ -455,6 +456,7 @@
\setinterfacevariable{subforward}{زیرجلوگرد}
\setinterfacevariable{subject}{موضوع}
\setinterfacevariable{subpage}{زیرصفحه}
+\setinterfacevariable{subs}{subs}
\setinterfacevariable{subsection}{زیربخش}
\setinterfacevariable{subsubject}{زیرموضوع}
\setinterfacevariable{subsubsection}{زیرزیربخش}
@@ -684,6 +686,7 @@
\setinterfaceconstant{filtercommand}{filtercommand}
\setinterfaceconstant{finalnamesep}{finalnamesep}
\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{firstpage}{صفحه‌اول}
\setinterfaceconstant{focus}{تمرکز}
\setinterfaceconstant{focusin}{تمرکزدرون}
\setinterfaceconstant{focusout}{تمرکزبیرون}
@@ -750,6 +753,7 @@
\setinterfaceconstant{label}{برچسب}
\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpage}{صفحه‌آخر}
\setinterfaceconstant{lastpubsep}{lastpubsep}
\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{چپ}
@@ -770,6 +774,7 @@
\setinterfaceconstant{leftsubsentence}{زیرجمله‌چپ}
\setinterfaceconstant{lefttext}{متن‌چپ}
\setinterfaceconstant{leftwidth}{عرض‌خط}
+\setinterfaceconstant{less}{less}
\setinterfaceconstant{level}{مرحله}
\setinterfaceconstant{levels}{مرحله‌ها}
\setinterfaceconstant{limittext}{مرزمتن}
@@ -808,6 +813,7 @@
\setinterfaceconstant{minheight}{کمترین‌ارتفاع}
\setinterfaceconstant{minwidth}{کمترین‌عرض}
\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{more}{more}
\setinterfaceconstant{n}{n}
\setinterfaceconstant{name}{نام}
\setinterfaceconstant{namesep}{namesep}
@@ -962,6 +968,7 @@
\setinterfaceconstant{separator}{جداکننده}
\setinterfaceconstant{set}{قراربده}
\setinterfaceconstant{setups}{بارگذاریها}
+\setinterfaceconstant{shrink}{shrink}
\setinterfaceconstant{side}{کنار}
\setinterfaceconstant{sidealign}{تنظیم‌کنار}
\setinterfaceconstant{sidemethod}{روش‌کنار}
@@ -970,6 +977,7 @@
\setinterfaceconstant{sign}{علامت}
\setinterfaceconstant{size}{اندازه}
\setinterfaceconstant{small}{کوچک}
+\setinterfaceconstant{solution}{solution}
\setinterfaceconstant{sort}{sort}
\setinterfaceconstant{sorttype}{ترتیب‌تایپ}
\setinterfaceconstant{source}{منبع}
diff --git a/tex/context/base/mult-prm.mkiv b/tex/context/base/mult-prm.mkiv
index 7e5bc1edd..8c9179a16 100644
--- a/tex/context/base/mult-prm.mkiv
+++ b/tex/context/base/mult-prm.mkiv
@@ -1,3 +1,18 @@
+%D \module
+%D [ file=mult-prm,
+%D version=2011.09.18, % actually older
+%D title=\CONTEXT\ Multilingual Macros,
+%D subtitle=Primitives,
+%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 therefore
+%C copyrighted by \PRAGMA. See mreadme.pdf for details.
+
+%D This file is only a helper for generating files that can be used in an
+%D editor for syntax highlighting.
+
\startluacode
context.starttext()
diff --git a/tex/context/base/mult-ro.mkii b/tex/context/base/mult-ro.mkii
index 1eef26e0d..adc811188 100644
--- a/tex/context/base/mult-ro.mkii
+++ b/tex/context/base/mult-ro.mkii
@@ -157,6 +157,7 @@
\setinterfacevariable{enumeration}{enumerare}
\setinterfacevariable{environment}{mediu}
\setinterfacevariable{even}{par}
+\setinterfacevariable{export}{export}
\setinterfacevariable{external}{extern}
\setinterfacevariable{fact}{fapt}
\setinterfacevariable{february}{februarie}
@@ -455,6 +456,7 @@
\setinterfacevariable{subforward}{subavans}
\setinterfacevariable{subject}{subiect}
\setinterfacevariable{subpage}{subpagina}
+\setinterfacevariable{subs}{subs}
\setinterfacevariable{subsection}{subsectiune}
\setinterfacevariable{subsubject}{subsubiect}
\setinterfacevariable{subsubsection}{subsubsectiune}
@@ -684,6 +686,7 @@
\setinterfaceconstant{filtercommand}{filtercommand}
\setinterfaceconstant{finalnamesep}{finalnamesep}
\setinterfaceconstant{firstnamesep}{firstnamesep}
+\setinterfaceconstant{firstpage}{primapagina}
\setinterfaceconstant{focus}{focus}
\setinterfaceconstant{focusin}{focusin}
\setinterfaceconstant{focusout}{focusout}
@@ -750,6 +753,7 @@
\setinterfaceconstant{label}{eticheta}
\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
+\setinterfaceconstant{lastpage}{ultimapagina}
\setinterfaceconstant{lastpubsep}{lastpubsep}
\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{stanga}
@@ -770,6 +774,7 @@
\setinterfaceconstant{leftsubsentence}{subpropozitiestanga}
\setinterfaceconstant{lefttext}{textstanga}
\setinterfaceconstant{leftwidth}{latimestanga}
+\setinterfaceconstant{less}{less}
\setinterfaceconstant{level}{nivel}
\setinterfaceconstant{levels}{nivele}
\setinterfaceconstant{limittext}{limittext}
@@ -808,6 +813,7 @@
\setinterfaceconstant{minheight}{inaltimeminima}
\setinterfaceconstant{minwidth}{latimeminima}
\setinterfaceconstant{monthconversion}{monthconversion}
+\setinterfaceconstant{more}{more}
\setinterfaceconstant{n}{n}
\setinterfaceconstant{name}{nume}
\setinterfaceconstant{namesep}{namesep}
@@ -962,6 +968,7 @@
\setinterfaceconstant{separator}{separator}
\setinterfaceconstant{set}{set}
\setinterfaceconstant{setups}{setups}
+\setinterfaceconstant{shrink}{shrink}
\setinterfaceconstant{side}{parte}
\setinterfaceconstant{sidealign}{sidealign}
\setinterfaceconstant{sidemethod}{sidemethod}
@@ -970,6 +977,7 @@
\setinterfaceconstant{sign}{semn}
\setinterfaceconstant{size}{dimensiune}
\setinterfaceconstant{small}{mic}
+\setinterfaceconstant{solution}{solution}
\setinterfaceconstant{sort}{sort}
\setinterfaceconstant{sorttype}{sorttype}
\setinterfaceconstant{source}{sursa}
diff --git a/tex/context/base/mult-sys.mkiv b/tex/context/base/mult-sys.mkiv
index 9b67ab4ba..be653f643 100644
--- a/tex/context/base/mult-sys.mkiv
+++ b/tex/context/base/mult-sys.mkiv
@@ -11,20 +11,19 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D In boring module we define a lot of obscure but useful
-%D system constants. By doing so we save lots of memory while
-%D at the same time we prevent ourself from typing errors.
+%D In boring module we define a lot of obscure but useful system constants.
+%D By doing so we save lots of memory while at the same time we prevent
+%D ourself making typing errors.
\writestatus{loading}{ConTeXt Multilingual Macros / System}
\unprotect
-%D This file is mostly the same as the \MKII\ variant but we
-%D keep extending \MKIV, so it was bout time to have a dedicated
-%D variant.
+%D This file is mostly the same as the \MKII\ variant but we keep extending
+%D \MKIV, so it was bout time to have a dedicated variant.
%D
-%D The constants are grouped in such a way that there is a
-%D minimal change of conflicts.
+%D The constants are grouped in such a way that there is a minimal change of
+%D conflicts.
%D
%D \starttyping
%D \definesystemconstants {word}
@@ -36,8 +35,8 @@
\definesystemconstant {hans}
\definesystemconstant {taco}
-%D First we define some system constants used for both the
-%D multi||lingual interface and multi||linguag typesetting.
+%D First we define some system constants used for both the multi||lingual
+%D interface and multi||linguag typesetting.
\definesystemconstant {afrikaans} \definesystemconstant {af}
\definesystemconstant {arabic} \definesystemconstant {ar}
@@ -83,8 +82,7 @@
\definesystemconstant {japanese} \definesystemconstant {ja}
\definesystemconstant {korean} \definesystemconstant {kr}
-%D For proper \UNICODE\ support we need a few font related
-%D constants.
+%D For proper \UNICODE\ support we need a few font related constants.
\definesystemconstant {BoldItalic}
\definesystemconstant {BoldSlanted}
@@ -115,7 +113,7 @@
\definesystemconstant {SerifSlanted}
\definesystemconstant {SerifBoldSlanted}
\definesystemconstant {SerifCaps}
-% \definesystemconstant {SerifCapsSlanted}
+%definesystemconstant {SerifCapsSlanted}
\definesystemconstant {Sans}
\definesystemconstant {SansBold}
@@ -155,6 +153,9 @@
%definesystemconstant {mnem} % kind of generic short tag
+\definesystemconstant {otr}
+\definesystemconstant {box}
+
\definesystemconstant {file}
\definesystemconstant {name}
\definesystemconstant {spec}
@@ -220,174 +221,176 @@
\definesystemconstant {second}
\definesystemconstant {third}
-%D Net come some \CONTEXT\ constants, used in the definition
-%D of private commands:
-
-\definesystemconstant {tex}
-\definesystemconstant {xml}
-\definesystemconstant {lua}
-
-\definesystemconstant {next}
-\definesystemconstant {pickup}
-\definesystemconstant {ascii}
-\definesystemconstant {default}
-\definesystemconstant {unknown}
-\definesystemconstant {action}
-\definesystemconstant {compare}
-\definesystemconstant {do}
-\definesystemconstant {dodo}
-\definesystemconstant {complex}
-\definesystemconstant {simple}
-\definesystemconstant {start}
-\definesystemconstant {stop}
-\definesystemconstant {dummy}
-\definesystemconstant {local}
-\definesystemconstant {global}
-\definesystemconstant {done}
-\definesystemconstant {font}
-\definesystemconstant {link}
-\definesystemconstant {parent}
-\definesystemconstant {child}
-\definesystemconstant {clone}
-\definesystemconstant {section}
-\definesystemconstant {handler}
-\definesystemconstant {counter}
-\definesystemconstant {single}
-\definesystemconstant {multi}
-\definesystemconstant {indeed}
-
-\definesystemconstant {hasnumber}
-\definesystemconstant {hastitle}
-\definesystemconstant {hascaption}
-\definesystemconstant {haslevel}
-
-\definesystemconstant {mkiv}
-\definesystemconstant {mkii}
-
-\definesystemconstant {normal}
-\definesystemconstant {bold}
-\definesystemconstant {italic}
-\definesystemconstant {slanted}
-
-\definesystemconstant {default}
-\definesystemconstant {smallcaps}
-
-\definesystemconstant {run}
-
-\definesystemconstant {mode}
-\definesystemconstant {setup}
-\definesystemconstant {environment}
-\definesystemconstant {document}
-
-%definesystemconstant {fam}
-\definesystemconstant {text}
-\definesystemconstant {script}
-\definesystemconstant {scriptscript}
-
-\definesystemconstant {lefthyphenmin}
-\definesystemconstant {righthyphenmin}
-\definesystemconstant {lefthyphenchar}
-\definesystemconstant {righthyphenchar}
-
-%definesystemconstant {skewchar}
-%definesystemconstant {hyphenchar}
-\definesystemconstant {catcodes}
-%definesystemconstant {encoding}
-%definesystemconstant {entities}
-%definesystemconstant {resource}
-%definesystemconstant {mapping}
-\definesystemconstant {language}
-\definesystemconstant {patterns}
-\definesystemconstant {rname}
-\definesystemconstant {rscale}
-%definesystemconstant {handling}
-\definesystemconstant {features}
-\definesystemconstant {direction}
-\definesystemconstant {fallbacks}
-\definesystemconstant {goodies}
-\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 {rgb}
-\definesystemconstant {cmyk}
-\definesystemconstant {gray}
-\definesystemconstant {spot}
-\definesystemconstant {all}
-\definesystemconstant {dtp}
-\definesystemconstant {none}
-
-\definesystemconstant {map}
-\definesystemconstant {special}
-\definesystemconstant {size}
-
-\definesystemconstant {depth}
-\definesystemconstant {nodepth}
+%D Next come some \CONTEXT\ constants, used in the definition of private commands:
+
+\definesystemconstant {tex}
+\definesystemconstant {xml}
+\definesystemconstant {lua}
+
+\definesystemconstant {next}
+\definesystemconstant {pickup}
+\definesystemconstant {ascii}
+\definesystemconstant {default}
+\definesystemconstant {unknown}
+\definesystemconstant {action}
+\definesystemconstant {compare}
+\definesystemconstant {do}
+\definesystemconstant {dodo}
+\definesystemconstant {complex}
+\definesystemconstant {simple}
+\definesystemconstant {start}
+\definesystemconstant {stop}
+\definesystemconstant {dummy}
+\definesystemconstant {local}
+\definesystemconstant {global}
+\definesystemconstant {done}
+\definesystemconstant {font}
+\definesystemconstant {link}
+\definesystemconstant {parent}
+\definesystemconstant {child}
+\definesystemconstant {clone}
+\definesystemconstant {section}
+\definesystemconstant {handler}
+\definesystemconstant {counter}
+\definesystemconstant {single}
+\definesystemconstant {multi}
+\definesystemconstant {indeed}
+
+% \def\s!parent{->} % 1% faster / => does not work in assignments
+% \def\s!child {<-} % 1% faster / <= does not work in assignments
+
+\definesystemconstant {hasnumber}
+\definesystemconstant {hastitle}
+\definesystemconstant {hascaption}
+\definesystemconstant {haslevel}
+
+\definesystemconstant {mkiv}
+\definesystemconstant {mkii}
+
+\definesystemconstant {normal}
+\definesystemconstant {bold}
+\definesystemconstant {italic}
+\definesystemconstant {slanted}
+
+\definesystemconstant {default}
+\definesystemconstant {smallcaps}
+
+\definesystemconstant {run}
+
+\definesystemconstant {mode}
+\definesystemconstant {setup}
+\definesystemconstant {environment}
+\definesystemconstant {document}
+
+%definesystemconstant {fam}
+\definesystemconstant {text}
+\definesystemconstant {script}
+\definesystemconstant {scriptscript}
+
+\definesystemconstant {lefthyphenmin}
+\definesystemconstant {righthyphenmin}
+\definesystemconstant {lefthyphenchar}
+\definesystemconstant {righthyphenchar}
+
+%definesystemconstant {skewchar}
+%definesystemconstant {hyphenchar}
+\definesystemconstant {catcodes}
+%definesystemconstant {encoding}
+%definesystemconstant {entities}
+%definesystemconstant {resource}
+%definesystemconstant {mapping}
+\definesystemconstant {language}
+\definesystemconstant {patterns}
+\definesystemconstant {rname}
+\definesystemconstant {rscale}
+%definesystemconstant {handling}
+\definesystemconstant {features}
+\definesystemconstant {direction}
+\definesystemconstant {fallbacks}
+\definesystemconstant {goodies}
+\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 {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.
-\definesystemconstant {cm}
-\definesystemconstant {em}
-\definesystemconstant {ex}
-\definesystemconstant {mm}
-\definesystemconstant {pt}
-\definesystemconstant {sp}
-\definesystemconstant {bp}
-\definesystemconstant {in}
-\definesystemconstant {pc}
-\definesystemconstant {dd}
-\definesystemconstant {cc}
-\definesystemconstant {nd}
-\definesystemconstant {nc}
-
-%D As the name of their define command states, the next set of
-%D constants is used in the message macro's.
+\definesystemconstant {cm}
+\definesystemconstant {em}
+\definesystemconstant {ex}
+\definesystemconstant {mm}
+\definesystemconstant {pt}
+\definesystemconstant {sp}
+\definesystemconstant {bp}
+\definesystemconstant {in}
+\definesystemconstant {pc}
+\definesystemconstant {dd}
+\definesystemconstant {cc}
+\definesystemconstant {nd}
+\definesystemconstant {nc}
+
+%D As the name of their define command states, the next set of constants is used in
+%D the message macro's.
\definemessageconstant {check}
\definemessageconstant {colors}
@@ -415,9 +418,8 @@
\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.
+%D When we use numbers and dimensions the same applies as with the keywords like
+%D \type {width} and \type {plus} mentioned earlier.
\def\!!ten {10}
\def\!!twelve {12}
@@ -447,138 +449,37 @@
\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.
-
-\definesystemvariable {ab} % AlignedBoxes
-\definesystemvariable {ac} % ACcent
-\definesystemvariable {ae} % AttributEs
-\definesystemvariable {al} % ALinea's
-\definesystemvariable {an} % ANchor
-\definesystemvariable {as} % AlignmentSwitch
-\definesystemvariable {bg} % BleedinG
-\definesystemvariable {bm} % BookMark
-\definesystemvariable {bp} % BreakPoint
-\definesystemvariable {bx} % BackendExport
-\definesystemvariable {cb} % CollectBox
-\definesystemvariable {cp} % CliP
-\definesystemvariable {da} % DAte
-\definesystemvariable {db} % Labels
-\definesystemvariable {dd} % DoorDefinieren
-\definesystemvariable {de} % DEel
-\definesystemvariable {dl} % DunneLijnen
-\definesystemvariable {dn} % DoorNummeren
-\definesystemvariable {dm} % DefineMeasure
-\definesystemvariable {du} % DUmmy
-\definesystemvariable {ef} % ExternFiguur
-\definesystemvariable {en} % ENvironments
-%definesystemvariable {er} % external resources
-\definesystemvariable {et} % EffecT
-\definesystemvariable {ex} % ExterneFiguren
-\definesystemvariable {fc} % FramedContent
-\definesystemvariable {fi} % FIle Once
-\definesystemvariable {fo} % xml FO (xtag)
-\definesystemvariable {fu} % FontSolution
+%D Variables are composed of a command specific tag and a user supplied variable
+%D (system constant). The tag \type {du} for instance is available as \type {\??du}
+%D and expands to \type {@@du} in composed variables.
+
+\definesystemvariable {du} % dummy, will stay
+
+% bibl:
+
+\definesystemvariable {pv} % PublicationVariable
+\definesystemvariable {pb} % PuBlication
+
+% needs checking (namespaces now)
+
\definesystemvariable {fw} % simpleFonts by Wolfgang
-\definesystemvariable {fx} % FoXet
-\definesystemvariable {gb} % Graphic Bitmaps
-\definesystemvariable {gv} % Graphic Variable
-\definesystemvariable {ha} % HAng
-\definesystemvariable {id} % Index
-\definesystemvariable {ih} % InHoudsopgave
-\definesystemvariable {il} % stelInvulRegelsin
-\definesystemvariable {ip} % InsertPages
-\definesystemvariable {is} % Items
-\definesystemvariable {it} % stelInTerliniein
-\definesystemvariable {iv} % stelInvulLijnenin
-\definesystemvariable {ka} % KAntlijn
-\definesystemvariable {kl} % KoLommen
-\definesystemvariable {km} % KenMerk
-\definesystemvariable {kp} % KopPelteken
-\definesystemvariable {ks} % KolomSpan
+
+% old pragma
+
\definesystemvariable {kt} % KonTakten
\definesystemvariable {kw} % KontaktWaarde
-\definesystemvariable {le} % LinetablE
-\definesystemvariable {lf} % LocalFigures
-\definesystemvariable {lg} % taal (LanGuage)
-\definesystemvariable {lk} % LinK
-\definesystemvariable {ll} % Layers
-\definesystemvariable {lr} % LayeR
-\definesystemvariable {lu} % LUacode
-\definesystemvariable {lx} % LayerteXt
-\definesystemvariable {ma} % MargeAchtergrond
-\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 {nn} % structurenumbering
-\definesystemvariable {nm} % Nummering
-\definesystemvariable {np} % NaastPlaatsen
-\definesystemvariable {nr} % Nummeren
-\definesystemvariable {ob} % OBjects
-\definesystemvariable {oi} % OmlijndInstellingen
-\definesystemvariable {ol} % OmLijnd
-\definesystemvariable {od} % Omlijnd Defaults (simple)
-\definesystemvariable {ox} % OffsetBox
-\definesystemvariable {pb} % PuBlication
-\definesystemvariable {pc} % PageComment
-\definesystemvariable {ph} % ParagrapH
-\definesystemvariable {pn} % PaginaNummer
-\definesystemvariable {pr} % PRogrammas
-\definesystemvariable {ps} % PoSitioneren
-\definesystemvariable {px} % Parallel
-\definesystemvariable {py} % PropertYs
-\definesystemvariable {pv} % PublicationVariable
-\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 {rs} % RaSters
-\definesystemvariable {rt} % RoosTers
-\definesystemvariable {rw} % RenderingWindow
-\definesystemvariable {sb} % SectieBlok
-\definesystemvariable {sd} % SounD
-\definesystemvariable {se} % SEctie
-\definesystemvariable {sh} % ShapeText
-\definesystemvariable {si} % SplIt
-\definesystemvariable {sp} % SelecteerPapier
\definesystemvariable {st} % STickers
-\definesystemvariable {sx} % Selector
-\definesystemvariable {ta} % TAb
-\definesystemvariable {tb} % TekstBlokken
-\definesystemvariable {te} % TEmplate
-\definesystemvariable {ti} % TabelInstellingen
-\definesystemvariable {tl} % TekstLijnen
-\definesystemvariable {tt} % TabulaTe
-\definesystemvariable {tx} % TeXtflow
-\definesystemvariable {ur} % URl
-\definesystemvariable {vn} % VoetNoten
-\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
+\definesystemvariable {km} % KenMerk
-% obsolete but kept for a while (core-obs)
+% mkii
-\definesystemvariable {fr} % Division
+\definesystemvariable {xf} % XML File (xtag)
+\definesystemvariable {xp} % XML Processing (xtag, so still needed)
+\definesystemvariable {fo} % xml FO (xtag)
+\definesystemvariable {fx} % FoXet
-%D Next we define some language independant one letter
-%D variables and keywords. We can actually make these
-%D system variables.
+%D Next we define some language independant one letter variables and keywords. We can
+%D actually make these system variables.
\defineinterfaceconstant {x} {x}
\defineinterfaceconstant {y} {y}
@@ -628,27 +529,25 @@
\def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi}
-%D The names of files and their extensions are fixed.
-%D \CONTEXT\ uses as less files as possible. Utility files can
-%D be recognized by the first two characters of the extension:
-%D \type{tu}.
+%D The names of files and their extensions are fixed. \CONTEXT\ uses as less
+%D files as possible. Utility files can be recognized by the first two
+%D characters of the extension: \type {tu}.
%definefileconstant {utilityfilename} {texutil}
%definefileconstant {blockextension} {tub}
%definefileconstant {figureextension} {tuf}
%definefileconstant {inputextension} {tui}
%definefileconstant {outputextension} {tuo} % tup for previous run
-\definefileconstant {optionextension} {top}
-\definefileconstant {temporaryextension} {tmp}
+%definefileconstant {optionextension} {top}
+%definefileconstant {temporaryextension} {tmp}
%definefileconstant {patternsextension} {pat}
%definefileconstant {hyphensextension} {hyp}
%definefileconstant {fontmapextension} {map}
\definefileconstant {bibextension} {bbl}
-%D These files are loaded at start||up. They may contain system
-%D specific setups (or calls to other files), old macro's, to
-%D garantee compatibility and new macro's noy yet present in
-%D the format.
+%D These files are loaded at start||up. They may contain system specific setups (or
+%D calls to other files), old macro's, to garantee compatibility and new macro's noy
+%D yet present in the format.
\definefileconstant {errfilename} {cont-err}
\definefileconstant {sysfilename} {cont-sys}
@@ -656,9 +555,8 @@
\definefileconstant {locfilename} {cont-loc}
\definefileconstant {expfilename} {cont-exp}
-%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.
+%D The setup files for the language, font, color and special subsystems have a common
+%D prefix. This means that we have at most three characters for unique filenames.
\definefileconstant {colorprefix} {colo-}
%definefileconstant {encodingprefix} {enco-}
@@ -717,20 +615,32 @@
%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
-%D not yet able to actually select an interface, because we
-%D still had to define the constants and variables. Now we've
-%D done so, selection is permitted.
+%D A careful reader will have noticed that in the module \type {mult-ini} we defined
+%D \type {\selectinterface}. We were not yet able to actually select an interface,
+%D because we still had to define the constants and variables. Now we've done so,
+%D selection is permitted.
\selectinterface
-%D Ok, here are some more, because we've got ouselves some
-%D extensions to \CONTEXT.
+%D Ok, here are some more, because we've got ouselves some extensions to \CONTEXT.
\definemessageconstant {addresses}
\definemessageconstant {documents}
-\protect
+%D Nicer than being undefined:
+
+\let\p_align \empty
+\let\p_aligntitle\empty
+\let\p_continue \empty
+\let\p_footer \empty
+\let\p_label \empty
+\let\p_number \empty
+\let\p_page \empty
+\let\p_state \empty
+\let\p_strut \empty
+\let\p_text \empty
+\let\p_tolerance \empty
+
+% more will follow
-\endinput
+\protect \endinput
diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua
index 43624adfd..03a8789f7 100644
--- a/tex/context/base/node-aux.lua
+++ b/tex/context/base/node-aux.lua
@@ -19,6 +19,7 @@ local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
+local attributelist_code = nodecodes.attributelist -- temporary
local nodepool = nodes.pool
@@ -35,14 +36,17 @@ local get_attribute = node.get_attribute
local unset_attribute = node.unset_attribute
local first_glyph = node.first_glyph or node.first_character
local copy_node = node.copy
+local copy_node_list = node.copy_list
local slide_nodes = node.slide
local insert_node_after = node.insert_after
local isnode = node.is_node
-local current_font = font.current()
+local current_font = font.current
local texbox = tex.box
+local report_error = logs.reporter("node-aux:error")
+
function nodes.repackhlist(list,...)
--~ nodes.showsimplelist(list)
local temp, b = hpack_nodes(list,...)
@@ -264,7 +268,7 @@ end
nodes.tonodes = tonodes
-local function link(head,tail,list,currentfont,currentattr)
+local function link(list,currentfont,currentattr,head,tail)
for i=1,#list do
local n = list[i]
if n then
@@ -272,6 +276,9 @@ local function link(head,tail,list,currentfont,currentattr)
if not tn then
local tn = type(n)
if tn == "number" then
+ if not currentfont then
+ currentfont = current_font()
+ end
local h, t = tonodes(tostring(n),currentfont,currentattr)
if not h then
-- skip
@@ -282,7 +289,10 @@ local function link(head,tail,list,currentfont,currentattr)
end
elseif tn == "string" then
if #tn > 0 then
- local h, t = tonodes(n,font.current(),currentattr)
+ if not currentfont then
+ currentfont = current_font()
+ end
+ local h, t = tonodes(n,currentfont,currentattr)
if not h then
-- skip
elseif not head then
@@ -293,7 +303,10 @@ local function link(head,tail,list,currentfont,currentattr)
end
elseif tn == "table" then
if #tn > 0 then
- head, tail = link(head,tail,n,currentfont,currentattr)
+ if not currentfont then
+ currentfont = current_font()
+ end
+ head, tail = link(n,currentfont,currentattr,head,tail)
end
end
elseif not head then
@@ -303,6 +316,18 @@ local function link(head,tail,list,currentfont,currentattr)
else
tail = n
end
+ elseif n.id == attributelist_code then
+ -- weird case
+ report_error("weird node type in list at index %s:",i)
+ for i=1,#list do
+ local l = list[i]
+ if l.id == attributelist_code then
+ report_error("%3i: ! %s",i,tostring(l))
+ else
+ report_error("%3i: > %s",i,tostring(l))
+ end
+ end
+ os.exit()
else
tail.next = n
n.prev = tail
@@ -319,10 +344,7 @@ local function link(head,tail,list,currentfont,currentattr)
return head, tail
end
-function nodes.link(...)
- local currentfont = font.current
- return link(nil,nil,{...},currentfont,currentattr)
-end
+nodes.link = link
local function locate(start,wantedid,wantedsubtype)
for n in traverse_nodes(start) do
@@ -342,7 +364,7 @@ end
nodes.locate = locate
-function nodes.concat(list) -- no slide !
+function nodes.concat(list)
local head, tail
for i=1,#list do
local li = list[i]
@@ -351,10 +373,10 @@ function nodes.concat(list) -- no slide !
elseif head then
tail.next = li
li.prev = tail
- tail = li
+ tail = li.next and slide_nodes(li) or li
else
head = li
- tail = li
+ tail = li.next and slide_nodes(li) or li
end
end
return head, tail
diff --git a/tex/context/base/node-dir.lua b/tex/context/base/node-dir.lua
index 970313d96..6ee5cd4b8 100644
--- a/tex/context/base/node-dir.lua
+++ b/tex/context/base/node-dir.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['node-mir'] = {
+if not modules then modules = { } end modules ['node-dir'] = {
version = 1.001,
comment = "companion to node-ini.mkiv",
author = "Taco Hoekwater and Hans Hagen",
diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua
index 5c1cc9ad5..27793716d 100644
--- a/tex/context/base/node-fin.lua
+++ b/tex/context/base/node-fin.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['node-fin'] = {
}
-- this module is being reconstructed
+-- local functions, only slightly slower
local next, type, format = next, type, string.format
@@ -14,6 +15,7 @@ local attributes, nodes, node = attributes, nodes, node
local has_attribute = node.has_attribute
local copy_node = node.copy
+local find_tail = node.slide
local nodecodes = nodes.nodecodes
local whatcodes = nodes.whatcodes
@@ -36,6 +38,8 @@ local triggering = false
local starttiming = statistics.starttiming
local stoptiming = statistics.stoptiming
+local unsetvalue = attributes.unsetvalue
+
-- these two will be like trackers
function states.enabletriggering()
@@ -176,6 +180,7 @@ local insert_node_after = node.insert_after
local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger
local current, current_selector, done = 0, 0, false -- nb, stack has a local current !
+local nsbegin, nsend
function states.initialize(namespace,attribute,head)
nsdata = namespace.data
@@ -187,6 +192,13 @@ function states.initialize(namespace,attribute,head)
current = 0
current_selector = 0
done = false -- todo: done cleanup
+ nsstep = namespace.resolve_step
+ if nsstep then
+ nsbegin = namespace.resolve_begin
+ nsend = namespace.resolve_end
+ nspush = namespace.push
+ nspop = namespace.pop
+ end
end
function states.finalize(namespace,attribute,head) -- is this one ok?
@@ -205,81 +217,167 @@ function states.finalize(namespace,attribute,head) -- is this one ok?
return head, false, false
end
+-- disc nodes can be ignored
+-- we need to deal with literals too (reset as well as oval)
+-- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then
+
+-- local function process(namespace,attribute,head,inheritance,default) -- one attribute
+-- local stack, done = head, false
+-- while stack do
+-- local id = stack.id
+-- if id == glyph_code or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code
+-- local c = has_attribute(stack,attribute)
+-- if c then
+-- if default and c == inheritance then
+-- if current ~= default then
+-- head = insert_node_before(head,stack,copy_node(nsdata[default]))
+-- current = default
+-- done = true
+-- end
+-- elseif current ~= c then
+-- head = insert_node_before(head,stack,copy_node(nsdata[c]))
+-- current = c
+-- done = true
+-- end
+-- -- here ? compare selective
+-- if id == glue_code then --leader
+-- -- same as *list
+-- local content = stack.leader
+-- if content then
+-- local savedcurrent = current
+-- local ci = content.id
+-- if ci == hlist_code or ci == vlist_code then
+-- -- else we reset inside a box unneeded, okay, the downside is
+-- -- that we trigger color in each repeated box, so there is room
+-- -- for improvement here
+-- current = 0
+-- end
+-- local ok = false
+-- if nstrigger and has_attribute(stack,nstrigger) then
+-- local outer = has_attribute(stack,attribute)
+-- if outer ~= inheritance then
+-- stack.leader, ok = process(namespace,attribute,content,inheritance,outer)
+-- else
+-- stack.leader, ok = process(namespace,attribute,content,inheritance,default)
+-- end
+-- else
+-- stack.leader, ok = process(namespace,attribute,content,inheritance,default)
+-- end
+-- current = savedcurrent
+-- done = done or ok
+-- end
+-- end
+-- elseif default and inheritance then
+-- if current ~= default then
+-- head = insert_node_before(head,stack,copy_node(nsdata[default]))
+-- current = default
+-- done = true
+-- end
+-- elseif current > 0 then
+-- head = insert_node_before(head,stack,copy_node(nsnone))
+-- current = 0
+-- done = true
+-- end
+-- elseif id == hlist_code or id == vlist_code then
+-- local content = stack.list
+-- if content then
+-- local ok = false
+-- if nstrigger and has_attribute(stack,nstrigger) then
+-- local outer = has_attribute(stack,attribute)
+-- if outer ~= inheritance then
+-- stack.list, ok = process(namespace,attribute,content,inheritance,outer)
+-- else
+-- stack.list, ok = process(namespace,attribute,content,inheritance,default)
+-- end
+-- else
+-- stack.list, ok = process(namespace,attribute,content,inheritance,default)
+-- end
+-- done = done or ok
+-- end
+-- end
+-- stack = stack.next
+-- end
+-- return head, done
+-- end
+
local function process(namespace,attribute,head,inheritance,default) -- one attribute
local stack, done = head, false
- while stack do
- local id = stack.id
- -- we need to deal with literals too (reset as well as oval)
- -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code
- if id == glyph_code -- or id == disc_code
- or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code
- local c = has_attribute(stack,attribute)
- if c then
- if default and c == inheritance then
- if current ~= default then
- head = insert_node_before(head,stack,copy_node(nsdata[default]))
- current = default
- done = true
- end
- elseif current ~= c then
- head = insert_node_before(head,stack,copy_node(nsdata[c]))
- current = c
- done = true
- end
- -- here ? compare selective
- if id == glue_code then --leader
- -- same as *list
- local content = stack.leader
- if content then
- local savedcurrent = current
- local ci = content.id
- if ci == hlist_code or ci == vlist_code then
- -- else we reset inside a box unneeded, okay, the downside is
- -- that we trigger color in each repeated box, so there is room
- -- for improvement here
- current = 0
- end
- local ok = false
- if nstrigger and has_attribute(stack,nstrigger) then
- local outer = has_attribute(stack,attribute)
- if outer ~= inheritance then
- stack.leader, ok = process(namespace,attribute,content,inheritance,outer)
- else
- stack.leader, ok = process(namespace,attribute,content,inheritance,default)
- end
- else
- stack.leader, ok = process(namespace,attribute,content,inheritance,default)
- end
- current = savedcurrent
- done = done or ok
- end
- end
- elseif default and inheritance then
+
+ local function check()
+ local c = has_attribute(stack,attribute)
+ if c then
+ if default and c == inheritance then
if current ~= default then
head = insert_node_before(head,stack,copy_node(nsdata[default]))
current = default
done = true
end
- elseif current > 0 then
- head = insert_node_before(head,stack,copy_node(nsnone))
- current = 0
+ elseif current ~= c then
+ head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ current = c
+ done = true
+ end
+ elseif default and inheritance then
+ if current ~= default then
+ head = insert_node_before(head,stack,copy_node(nsdata[default]))
+ current = default
done = true
end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ current = 0
+ done = true
+ end
+ return c
+ end
+
+ local function nested(content)
+ if nstrigger and has_attribute(stack,nstrigger) then
+ local outer = has_attribute(stack,attribute)
+ if outer ~= inheritance then
+ return process(namespace,attribute,content,inheritance,outer)
+ else
+ return process(namespace,attribute,content,inheritance,default)
+ end
+ else
+ return process(namespace,attribute,content,inheritance,default)
+ end
+ end
+
+ while stack do
+ local id = stack.id
+ if id == glyph_code then
+ check()
+ elseif id == rule_code then
+ if stack.width ~= 0 then
+ check()
+ end
+ elseif id == glue_code then
+ local content = stack.leader
+ if content and check() then
+ local savedcurrent = current
+ local ci = content.id
+ if ci == hlist_code or ci == vlist_code then
+ -- else we reset inside a box unneeded, okay, the downside is
+ -- that we trigger color in each repeated box, so there is room
+ -- for improvement here
+ current = 0
+ end
+
+ local ok = false
+ stack.leader, ok = nested(content)
+ done = done or ok
+
+ current = savedcurrent
+ end
elseif id == hlist_code or id == vlist_code then
local content = stack.list
if content then
+
local ok = false
- if nstrigger and has_attribute(stack,nstrigger) then
- local outer = has_attribute(stack,attribute)
- if outer ~= inheritance then
- stack.list, ok = process(namespace,attribute,content,inheritance,outer)
- else
- stack.list, ok = process(namespace,attribute,content,inheritance,default)
- end
- else
- stack.list, ok = process(namespace,attribute,content,inheritance,default)
- end
+ stack.list, ok = nested(content)
done = done or ok
+
end
end
stack = stack.next
@@ -295,86 +393,185 @@ states.process = process
-- state changes while the main state stays the same (like two glyphs following
-- each other with the same color but different color spaces e.g. \showcolor)
+-- local function selective(namespace,attribute,head,inheritance,default) -- two attributes
+-- local stack, done = head, false
+-- while stack do
+-- local id = stack.id
+-- -- we need to deal with literals too (reset as well as oval)
+-- -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code
+-- if id == glyph_code -- or id == disc_code
+-- or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code
+-- local c = has_attribute(stack,attribute)
+-- if c then
+-- if default and c == inheritance then
+-- if current ~= default then
+-- local data = nsdata[default]
+-- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
+-- current = default
+-- done = true
+-- end
+-- else
+-- local s = has_attribute(stack,nsselector)
+-- if current ~= c or current_selector ~= s then
+-- local data = nsdata[c]
+-- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
+-- current = c
+-- current_selector = s
+-- done = true
+-- end
+-- end
+-- elseif default and inheritance then
+-- if current ~= default then
+-- local data = nsdata[default]
+-- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
+-- current = default
+-- done = true
+-- end
+-- elseif current > 0 then
+-- head = insert_node_before(head,stack,copy_node(nsnone))
+-- current, current_selector, done = 0, 0, true
+-- end
+-- if id == glue_code then -- leader
+-- -- same as *list
+-- local content = stack.leader
+-- if content then
+-- local savedcurrent = current
+-- local ci = content.id
+-- if ci == hlist_code or ci == vlist_code then
+-- -- else we reset inside a box unneeded, okay, the downside is
+-- -- that we trigger color in each repeated box, so there is room
+-- -- for improvement here
+-- current = 0
+-- end
+-- local ok = false
+-- if nstrigger and has_attribute(stack,nstrigger) then
+-- local outer = has_attribute(stack,attribute)
+-- if outer ~= inheritance then
+-- stack.leader, ok = selective(namespace,attribute,content,inheritance,outer)
+-- else
+-- stack.leader, ok = selective(namespace,attribute,content,inheritance,default)
+-- end
+-- else
+-- stack.leader, ok = selective(namespace,attribute,content,inheritance,default)
+-- end
+-- current = savedcurrent
+-- done = done or ok
+-- end
+-- end
+-- elseif id == hlist_code or id == vlist_code then
+-- local content = stack.list
+-- if content then
+-- local ok = false
+-- if nstrigger and has_attribute(stack,nstrigger) then
+-- local outer = has_attribute(stack,attribute)
+-- if outer ~= inheritance then
+-- stack.list, ok = selective(namespace,attribute,content,inheritance,outer)
+-- else
+-- stack.list, ok = selective(namespace,attribute,content,inheritance,default)
+-- end
+-- else
+-- stack.list, ok = selective(namespace,attribute,content,inheritance,default)
+-- end
+-- done = done or ok
+-- end
+-- end
+-- stack = stack.next
+-- end
+-- return head, done
+-- end
+
local function selective(namespace,attribute,head,inheritance,default) -- two attributes
local stack, done = head, false
- while stack do
- local id = stack.id
- -- we need to deal with literals too (reset as well as oval)
- -- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code
- if id == glyph_code -- or id == disc_code
- or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code
- local c = has_attribute(stack,attribute)
- if c then
- if default and c == inheritance then
- if current ~= default then
- local data = nsdata[default]
- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
- current = default
- done = true
- end
- else
- local s = has_attribute(stack,nsselector)
- if current ~= c or current_selector ~= s then
- local data = nsdata[c]
- head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
- current = c
- current_selector = s
- done = true
- end
- end
- elseif default and inheritance then
+
+ local function check()
+ local c = has_attribute(stack,attribute)
+ if c then
+ if default and c == inheritance then
if current ~= default then
local data = nsdata[default]
head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
current = default
done = true
end
- elseif current > 0 then
- head = insert_node_before(head,stack,copy_node(nsnone))
- current, current_selector, done = 0, 0, true
+ else
+ local s = has_attribute(stack,nsselector)
+ if current ~= c or current_selector ~= s then
+ local data = nsdata[c]
+ head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
+ current = c
+ current_selector = s
+ done = true
+ end
end
- if id == glue_code then -- leader
- -- same as *list
- local content = stack.leader
- if content then
- local savedcurrent = current
- local ci = content.id
- if ci == hlist_code or ci == vlist_code then
- -- else we reset inside a box unneeded, okay, the downside is
- -- that we trigger color in each repeated box, so there is room
- -- for improvement here
- current = 0
- end
- local ok = false
- if nstrigger and has_attribute(stack,nstrigger) then
- local outer = has_attribute(stack,attribute)
- if outer ~= inheritance then
- stack.leader, ok = selective(namespace,attribute,content,inheritance,outer)
- else
- stack.leader, ok = selective(namespace,attribute,content,inheritance,default)
- end
- else
- stack.leader, ok = selective(namespace,attribute,content,inheritance,default)
- end
- current = savedcurrent
- done = done or ok
+ elseif default and inheritance then
+ if current ~= default then
+ local data = nsdata[default]
+ head = insert_node_before(head,stack,copy_node(data[nsforced or has_attribute(stack,nsselector) or nsselector]))
+ current = default
+ done = true
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ current, current_selector, done = 0, 0, true
+ end
+ return c
+ end
+
+ local function nested(content)
+ if nstrigger and has_attribute(stack,nstrigger) then
+ local outer = has_attribute(stack,attribute)
+ if outer ~= inheritance then
+ return selective(namespace,attribute,content,inheritance,outer)
+ else
+ return selective(namespace,attribute,content,inheritance,default)
+ end
+ else
+ return selective(namespace,attribute,content,inheritance,default)
+ end
+ end
+
+ while stack do
+ local id = stack.id
+ if id == glyph_code then
+ check()
+ elseif id == rule_code then
+ if stack.width ~= 0 then
+ check()
+ end
+ elseif id == glue_code then
+ local content = stack.leader
+ if content and check() then
+ local savedcurrent = current
+ local ci = content.id
+ if ci == hlist_code or ci == vlist_code then
+ -- else we reset inside a box unneeded, okay, the downside is
+ -- that we trigger color in each repeated box, so there is room
+ -- for improvement here
+ current = 0
end
+
+ local ok = false
+ stack.leader, ok = nested(content)
+ done = done or ok
+
+ current = savedcurrent
end
elseif id == hlist_code or id == vlist_code then
local content = stack.list
if content then
+
local ok = false
- if nstrigger and has_attribute(stack,nstrigger) then
- local outer = has_attribute(stack,attribute)
- if outer ~= inheritance then
- stack.list, ok = selective(namespace,attribute,content,inheritance,outer)
- else
- stack.list, ok = selective(namespace,attribute,content,inheritance,default)
- end
- else
- stack.list, ok = selective(namespace,attribute,content,inheritance,default)
- end
+ stack.list, ok = nested(content)
done = done or ok
+
+ -- nicer:
+ --
+ -- local content, ok = nested(content)
+ -- if ok then
+ -- stack.leader = content
+ -- done = true
+ -- end
+
end
end
stack = stack.next
@@ -382,53 +579,65 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
return head, done
end
+
states.selective = selective
-- Ideally the next one should be merged with the previous but keeping it separate is
-- safer. We deal with two situations: efficient boxwise (layoutareas) and mixed layers
-- (as used in the stepper). In the stepper we cannot use the box branch as it involves
--- paragraph lines and then getsmixed up. A messy business (esp since we want to be
+-- paragraph lines and then gets mixed up. A messy business (esp since we want to be
-- efficient).
+--
+-- Todo: make a better stacker. Keep track (in attribute) about nesting level. Not
+-- entirely trivial and a generic solution is nicer (compares to the exporter).
local function stacked(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise
local stack, done = head, false
local current, depth = default or 0, 0
+
+ local function check()
+ local a = has_attribute(stack,attribute)
+ if a then
+ if current ~= a then
+ head = insert_node_before(head,stack,copy_node(nsdata[a]))
+ depth = depth + 1
+ current, done = a, true
+ end
+ elseif default > 0 then
+ --
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ depth = depth - 1
+ current, done = 0, true
+ end
+ return a
+ end
+
while stack do
local id = stack.id
- if id == glyph_code or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then -- or disc_code
- local c = has_attribute(stack,attribute)
- if c then
- if current ~= c then
- head = insert_node_before(head,stack,copy_node(nsdata[c]))
- depth = depth + 1
- current, done = c, true
- end
- if id == glue_code then
- local content = stack.leader
- if content then -- unchecked
- local ok = false
- stack.leader, ok = stacked(namespace,attribute,content,current)
- done = done or ok
- end
- end
---~ elseif default then
- elseif default > 0 then
- --
- elseif current > 0 then
- head = insert_node_before(head,stack,copy_node(nsnone))
- depth = depth - 1
- current, done = 0, true
+ if id == glyph_code then
+ check()
+ elseif id == rule_code then
+ if stack.width ~= 0 then
+ check()
+ end
+ elseif id == glue_code then
+ local content = stack.leader
+ if content and check() then
+ local ok = false
+ stack.leader, ok = stacked(namespace,attribute,content,current)
+ done = done or ok
end
elseif id == hlist_code or id == vlist_code then
local content = stack.list
if content then
-- the problem is that broken lines gets the attribute which can be a later one
if nslistwise then
- local c = has_attribute(stack,attribute)
- if c and current ~= c and nslistwise[c] then -- viewerlayer
+ local a = has_attribute(stack,attribute)
+ if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below
local p = current
- current, done = c, true
- head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ current, done = a, true
+ head = insert_node_before(head,stack,copy_node(nsdata[a]))
stack.list = stacked(namespace,attribute,content,current)
head, stack = insert_node_after(head,stack,copy_node(nsnone))
current = p
@@ -448,13 +657,87 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
end
while depth > 0 do
head = insert_node_after(head,stack,copy_node(nsnone))
- depth = depth -1
+ depth = depth - 1
end
return head, done
end
states.stacked = stacked
+-- experimental
+
+local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise
+ nsbegin()
+ local current, previous, done, okay = head, head, false, false
+ local attrib = default or unsetvalue
+
+ local function check()
+ local a = has_attribute(current,attribute) or unsetvalue
+ if a ~= attrib then
+ local n = nsstep(a)
+ if n then
+ -- !!!! TEST CODE !!!!
+-- head = insert_node_before(head,current,copy_node(nsdata[tonumber(n)])) -- a
+ head = insert_node_before(head,current,n) -- a
+ end
+ attrib, done, okay = a, true, true
+ end
+ return a
+ end
+
+ while current do
+ local id = current.id
+ if id == glyph_code then
+ check()
+ elseif id == glue_code then
+ local content = current.leader
+ if content and check() then
+ -- tricky as a leader has to be a list so we cannot inject before
+ local _, ok = stacker(namespace,attribute,content,attrib)
+ done = done or ok
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local content = current.list
+ if not content then
+ -- skip
+ elseif nslistwise then
+ local a = has_attribute(current,attribute)
+ if a and attrib ~= a and nslistwise[a] then -- viewerlayer
+ done = true
+ head = insert_node_before(head,current,copy_node(nsdata[a]))
+ current.list = stacker(namespace,attribute,content,a)
+ head, current = insert_node_after(head,current,copy_node(nsnone))
+ else
+ local ok = false
+ current.list, ok = stacker(namespace,attribute,content,attrib)
+ done = done or ok
+ end
+ else
+ local ok = false
+ current.list, ok = stacker(namespace,attribute,content,default)
+ done = done or ok
+ end
+ elseif id == rule_code then
+ if current.width ~= 0 then
+ check()
+ end
+ end
+ previous = current
+ current = current.next
+ end
+ if okay then
+ local n = nsend()
+ if n then
+ -- !!!! TEST CODE !!!!
+-- head = insert_node_after(head,previous,copy_node(nsdata[tostring(n)]))
+ head = insert_node_after(head,previous,n)
+ end
+ end
+ return head, done
+end
+
+states.stacker = stacker
+
-- -- --
statistics.register("attribute processing time", function()
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua
index 0ed17a1b5..e654d9e0f 100644
--- a/tex/context/base/node-ini.lua
+++ b/tex/context/base/node-ini.lua
@@ -73,25 +73,29 @@ nodes.handlers = nodes.handlers or { }
-- there will be more of this:
local skipcodes = allocate {
- [ 0] = "userskip",
- [ 1] = "lineskip",
- [ 2] = "baselineskip",
- [ 3] = "parskip",
- [ 4] = "abovedisplayskip",
- [ 5] = "belowdisplayskip",
- [ 6] = "abovedisplayshortskip",
- [ 7] = "belowdisplayshortskip",
- [ 8] = "leftskip",
- [ 9] = "rightskip",
- [10] = "topskip",
- [11] = "splittopskip",
- [12] = "tabskip",
- [13] = "spaceskip",
- [14] = "xspaceskip",
- [15] = "parfillskip",
- [16] = "thinmuskip",
- [17] = "medmuskip",
- [18] = "thickmuskip",
+ [ 0] = "userskip",
+ [ 1] = "lineskip",
+ [ 2] = "baselineskip",
+ [ 3] = "parskip",
+ [ 4] = "abovedisplayskip",
+ [ 5] = "belowdisplayskip",
+ [ 6] = "abovedisplayshortskip",
+ [ 7] = "belowdisplayshortskip",
+ [ 8] = "leftskip",
+ [ 9] = "rightskip",
+ [ 10] = "topskip",
+ [ 11] = "splittopskip",
+ [ 12] = "tabskip",
+ [ 13] = "spaceskip",
+ [ 14] = "xspaceskip",
+ [ 15] = "parfillskip",
+ [ 16] = "thinmuskip",
+ [ 17] = "medmuskip",
+ [ 18] = "thickmuskip",
+ [100] = "leaders",
+ [101] = "cleaders",
+ [102] = "xleaders",
+ [103] = "gleaders",
}
local penaltycodes = allocate { -- unfortunately not used
diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua
index 246aaade2..2cbcc8b88 100644
--- a/tex/context/base/node-inj.lua
+++ b/tex/context/base/node-inj.lua
@@ -34,7 +34,6 @@ 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
@@ -46,27 +45,16 @@ 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.
+function injections.installnewkern(nk)
+ newkern = nk or newkern
+end
+
local cursives = { }
local marks = { }
local kerns = { }
@@ -352,16 +340,13 @@ function injections.handler(head,where,keep)
-- new per 2010-10-06, width adapted per 2010-02-03
-- we used to negate the width of marks because in tfm
-- 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
- -- one is right
+ -- consequence the sign of p.width was changed
local k = wx[p]
if k then
- n.xoffset = p.xoffset + p.width + d[1] - k[2]
+ -- brill roman: A\char"0300 (but ugly anyway)
+ n.xoffset = p.xoffset - p.width + d[1] - k[2] -- was + p.width
else
- -- n.xoffset = p.xoffset + p.width + d[1]
- -- lucida U\char"032F (default+mark)
+ -- lucida: U\char"032F (default+mark)
n.xoffset = p.xoffset - p.width + d[1] -- 01-05-2011
end
else
diff --git a/tex/context/base/node-par.mkiv b/tex/context/base/node-par.mkiv
deleted file mode 100644
index 685167e8a..000000000
--- a/tex/context/base/node-par.mkiv
+++ /dev/null
@@ -1,82 +0,0 @@
-%D \module
-%D [ file=node-par,
-%D version=2008.09.30,
-%D title=\CONTEXT\ Node Macros,
-%D subtitle=Paragraph Building,
-%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 Node Macros / Paragraph Building}
-
-%D This is very experimental, undocumented, subjected to changes, etc. just as
-%D the underlying interfaces.
-
-% \enableparbuilders
-%
-% \startparbuilder[default]
-% \input tufte \par
-% \startparbuilder[oneline]
-% \input tufte \par
-% \stopparbuilder
-% \input tufte \par
-% \stopparbuilder
-
-\unprotect
-
-\registerctxluafile{node-par}{1.001}
-
-\definesystemattribute[parbuilder][public]
-
-% todo auto-enable
-
-% management (enable/disable) is global and will move to lua
-
-\installcorenamespace {parbuilder}
-
-\newcount\c_node_paragraphs_n_of_builders
-
-\let\m_node_paragraphs_current_builder\empty
-
-\unexpanded\def\defineparbuilder[#1]%
- {\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\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\m_node_paragraphs_current_builder
- \attribute\parbuilderattribute\m_node_paragraphs_current_builder\relax
- \node_paragraphs_builders_check}
-
-\unexpanded\def\setmainparbuilder[#1]%
- {\ctxlua{builders.paragraphs.constructors.set("#1")}}
-
-% no high level interface, after all implementing a linebreaker is not something that
-% the average user will do
-
-\defineparbuilder[default] % just for testing
-\defineparbuilder[oneline] % just for testing
-\defineparbuilder[basic] % just for testing
-
-\def\enableparbuilders {\ctxlua{builders.paragraphs.constructors.enable ()}}
-\def\disableparbuilders{\ctxlua{builders.paragraphs.constructors.disable()}}
-
-\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
- \enableparbuilders
- \fi}
-
-\protect \endinput
diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua
index dc1410282..2896c0d67 100644
--- a/tex/context/base/node-ref.lua
+++ b/tex/context/base/node-ref.lua
@@ -1,6 +1,6 @@
-if not modules then modules = { } end modules ['node-bck'] = {
+if not modules then modules = { } end modules ['node-ref'] = {
version = 1.001,
- comment = "companion to node-bck.mkiv",
+ comment = "companion to node-ref.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
@@ -493,12 +493,12 @@ local function makedestination(width,height,depth,reference)
for n=1,#name do
local annot = nodeinjections.destination(width,height,depth,name[n],view)
if not result then
- result, current = annot, annot
+ result = annot
else
current.next = annot
annot.prev = current
- current = annot
end
+ current = find_node_tail(annot)
end
if result then
-- some internal error
@@ -544,6 +544,9 @@ function references.injectcurrentset(h,d) -- used inside doifelse
end
end
+commands.injectreference = references.inject
+commands.injectcurrentreference = references.injectcurrentset
+
--
local function checkboth(open,close)
diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua
index 4522bef98..2933fc86d 100644
--- a/tex/context/base/node-res.lua
+++ b/tex/context/base/node-res.lua
@@ -33,6 +33,8 @@ local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
+local allocate = utilities.storage.allocate
+
local reserved, nofreserved = { }, 0
local function register_node(n)
@@ -83,7 +85,6 @@ local glue = register_node(new_node("glue")) -- glue.spec = nil
local glue_spec = register_node(new_node("glue_spec"))
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
@@ -99,6 +100,12 @@ local rightskip = register_node(new_node("glue",skipcodes.rightskip))
local temp = register_node(new_node("temp",0))
local noad = register_node(new_node("noad"))
+-- the dir field needs to be set otherwise crash:
+
+local rule = register_node(new_node("rule")) rule .dir = "TLT"
+local hlist = register_node(new_node("hlist")) hlist.dir = "TLT"
+local vlist = register_node(new_node("vlist")) vlist.dir = "TLT"
+
function pool.zeroglue(n)
local s = n.spec
return not writable or (
@@ -284,6 +291,14 @@ function pool.noad()
return copy_node(noad)
end
+function pool.hlist()
+ return copy_node(hlist)
+end
+
+function pool.vlist()
+ return copy_node(vlist)
+end
+
--[[
<p>At some point we ran into a problem that the glue specification
of the zeropoint dimension was overwritten when adapting a glue spec
@@ -312,7 +327,7 @@ end
-- local num = userids["my id"]
-- local str = userids[num]
-local userids = utilities.storage.allocate() pool.userids = userids
+local userids = allocate() pool.userids = userids
local lastid = 0
setmetatable(userids, {
diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua
index 7f49edffc..d81016af0 100644
--- a/tex/context/base/node-rul.lua
+++ b/tex/context/base/node-rul.lua
@@ -86,6 +86,7 @@ local hpack_nodes = node.hpack
local fontdata = fonts.hashes.identifiers
local variables = interfaces.variables
local dimenfactor = fonts.helpers.dimenfactor
+local splitdimen = number.splitdimen
local nodecodes = nodes.nodecodes
local skipcodes = nodes.skipcodes
@@ -258,26 +259,43 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a
return head
end
local w = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,f,l.next)
- local method, offset, continue, dy, rulethickness, unit, order, max, ma, ca, ta =
- d.method, d.offset, d.continue, d.dy, d.rulethickness, d.unit, d.order, d.max, d.ma, d.ca, d.ta
- local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node
+ local method, offset, continue, dy, order, max = d.method, d.offset, d.continue, d.dy, d.order, d.max
+ local rulethickness, unit = d.rulethickness, d.unit
+ local ma, ca, ta = d.ma, d.ca, d.ta
local colorspace = (ma > 0 and ma) or has_attribute(f,a_colorspace) or 1
local color = (ca > 0 and ca) or has_attribute(f,a_color)
local transparency = (ta > 0 and ta) or has_attribute(f,a_transparency)
local foreground = order == variables.foreground
- rulethickness= rulethickness/2
+
+ local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node
+
+ local rt = tonumber(rulethickness)
+ if rt then
+ rulethickness = e * rulethickness / 2
+ else
+ local n, u = splitdimen(rulethickness)
+ if n and u then -- we need to intercept ex and em and % and ...
+ rulethickness = n * dimenfactor(u,fontdata[f.font]) / 2
+ else
+ rulethickness = 1/5
+ end
+ end
+
if level > max then
level = max
end
if method == 0 then -- center
offset = 2*offset
- m = (offset+(level-1)*dy+rulethickness)*e/2
+-- m = (offset+(level-1)*dy+rulethickness)*e/2
+ m = (offset+(level-1)*dy)*e/2 + rulethickness/2
else
m = 0
end
for i=1,level do
- local ht = (offset+(i-1)*dy+rulethickness)*e - m
- local dp = -(offset+(i-1)*dy-rulethickness)*e + m
+-- local ht = (offset+(i-1)*dy+rulethickness)*e - m
+-- local dp = -(offset+(i-1)*dy-rulethickness)*e + m
+ local ht = (offset+(i-1)*dy)*e + rulethickness - m
+ local dp = -(offset+(i-1)*dy)*e + rulethickness + m
local r = new_rule(w,ht,dp)
local v = has_attribute(f,a_viewerlayer)
-- quick hack
diff --git a/tex/context/base/node-rul.mkiv b/tex/context/base/node-rul.mkiv
index 1f1ac20ec..54a43a006 100644
--- a/tex/context/base/node-rul.mkiv
+++ b/tex/context/base/node-rul.mkiv
@@ -21,15 +21,14 @@
%D overstrike,overstrikes,
%D setupbar}
%D
-%D In the rare case that we need undelined words, for instance
-%D because all font alternatives are already in use, one can
-%D use \type{\underbar} and \type{\overstrike} and their plural
-%D forms.
+%D In the rare case that we need undelined words, for instance because all font
+%D alternatives are already in use, one can use \type {\underbar} and \type
+%D {\overstrike} and their plural forms.
%D
%D \startbuffer
-%D \underbars{drawing \underbar{bars} under words is a typewriter leftover}
-%D \overstrikes{striking words makes them \overstrike{unreadable} but
-%D sometimes even \overbar{top lines} come into view.}
+%D \underbars {drawing \underbar{bars} under words is a typewriter leftover}
+%D \overstrikes {striking words makes them \overstrike {unreadable} but
+%D sometimes even \overbar {top lines} come into view.}
%D \stopbuffer
%D
%D \typebuffer
@@ -38,9 +37,9 @@
%D \getbuffer
%D \stoplines
%D
-%D The next macros are derived from the \PLAIN\ \TEX\ one, but
-%D also supports nesting. The \type{$} keeps us in horizontal
-%D mode and at the same time applies grouping.
+%D The next macros are derived from the \PLAIN\ \TEX\ one, but also supports
+%D nesting. The \type{$} keeps us in horizontal mode and at the same time
+%D applies grouping.
%D
%D \showsetup{underbar}
%D \showsetup{underbars}
@@ -51,9 +50,19 @@
%D
%D \showsetup{setupunderbar}
%D
-%D Nested bars can be configured by appending \type {:<index>} to the
-%D category.
-
+%D Nested bars can be configured by appending \type {:<index>} to the category.
+%D Normally units in combination with a unitless thickness specification but
+%D there units can be used too.
+%D
+%D \startbuffer
+%D \setupbars[unit=mm,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank
+%D \setupbars[unit=ex,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank
+%D \setupbars[unit=pt,rulethickness=1] bar\startbar[underbar]foo\stopbar bar\blank
+%D \setupbars[unit=pt,rulethickness=10pt] bar\startbar[underbar]foo\stopbar bar
+%D \stopbuffer
+%D
+%D \typebuffer \blank \getbuffer \blank
+%D
%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
@@ -107,7 +116,7 @@
offset = \barparameter\c!offset,
continue = "\barparameter\c!continue",
dy = \barparameter\c!dy,
- rulethickness = \barparameter\c!rulethickness,
+ rulethickness = "\barparameter\c!rulethickness",
unit = "\barparameter\c!unit",
order = "\barparameter\c!order",
max = \barparameter\c!max,
@@ -286,9 +295,6 @@
\c!style=,
\c!color=]
-\def\v!shiftup {shiftup}
-\def\v!shiftdown{shiftdown}
-
\defineshift [\v!shiftup] [\c!method=0,\c!dy=-1,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=]
\defineshift [\v!shiftdown] [\c!method=1,\c!dy=.3,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=]
diff --git a/tex/context/base/node-ser.lua b/tex/context/base/node-ser.lua
index 63690d00a..8e999f520 100644
--- a/tex/context/base/node-ser.lua
+++ b/tex/context/base/node-ser.lua
@@ -19,6 +19,7 @@ local nodes, node = nodes, node
local traverse = node.traverse
local nodecodes = nodes.nodecodes
+local noadcodes = nodes.noadcodes
local nodefields = nodes.fields
local hlist_code = nodecodes.hlist
@@ -39,6 +40,7 @@ local expand = allocate ( tohash {
"leader", -- leader_ptr
"action", -- action_ptr
"value", -- user_defined nodes with subtype 'a' en 'n'
+ "head",
} )
-- page_insert: "height", "last_ins_ptr", "best_ins_ptr"
@@ -94,9 +96,9 @@ end
-- under construction:
-local function totable(n,flat,verbose) -- todo: no attributes
+local function totable(n,flat,verbose,noattributes)
-- todo: no local function
- local function to_table(n,flat,verbose)
+ local function to_table(n,flat,verbose,noattributes) -- no need to pass
local f = nodefields(n)
local tt = { }
for k=1,#f do
@@ -105,6 +107,8 @@ local function totable(n,flat,verbose) -- todo: no attributes
if nv then
if ignore[v] then
-- skip
+ elseif noattributes and v == "attr" then
+ -- skip
elseif expand[v] then
if type(nv) == "number" or type(nv) == "string" then
tt[v] = nv
@@ -128,14 +132,14 @@ local function totable(n,flat,verbose) -- todo: no attributes
local t, tn = { }, 0
while n do
tn = tn + 1
- t[tn] = to_table(n,flat,verbose)
+ t[tn] = to_table(n,flat,verbose,noattributes)
n = n.next
end
return t
else
local t = to_table(n)
if n.next then
- t.next = totable(n.next,flat,verbose)
+ t.next = totable(n.next,flat,verbose,noattributes)
end
return t
end
@@ -154,7 +158,7 @@ end
-- todo: adapt to nodecodes etc
-local function serialize(root,name,handle,depth,m)
+local function serialize(root,name,handle,depth,m,noattributes)
handle = handle or print
if depth then
depth = depth .. " "
@@ -188,6 +192,11 @@ local function serialize(root,name,handle,depth,m)
local k = fld[f]
if k == "ref_count" then
-- skip
+ elseif noattributes and k == "attr" then
+ -- skip
+ elseif k == "id" then
+ local v = root[k]
+ handle(format("%s id=%s,",depth,nodecodes[v] or noadcodes[v] or v))
elseif k then
local v = root[k]
local t = type(v)
@@ -206,12 +215,12 @@ local function serialize(root,name,handle,depth,m)
elseif t == "boolean" then
handle(format("%s %s=%q,",depth,key(k),tostring(v)))
elseif v then -- userdata or table
- serialize(v,k,handle,depth,m+1)
+ serialize(v,k,handle,depth,m+1,noattributes)
end
end
end
if root['next'] then -- userdata or table
- serialize(root['next'],'next',handle,depth,m+1)
+ serialize(root['next'],'next',handle,depth,m+1,noattributes)
end
end
if m and m > 0 then
@@ -221,13 +230,13 @@ local function serialize(root,name,handle,depth,m)
end
end
-function nodes.serialize(root,name)
+function nodes.serialize(root,name,noattributes)
local t, n = { }, 0
local function flush(s)
n = n + 1
t[n] = s
end
- serialize(root, name, flush, nil, 0)
+ serialize(root,name,flush,nil,0,noattributes)
return concat(t,"\n")
end
diff --git a/tex/context/base/node-spl.lua b/tex/context/base/node-spl.lua
deleted file mode 100644
index 3b208e0e7..000000000
--- a/tex/context/base/node-spl.lua
+++ /dev/null
@@ -1,619 +0,0 @@
-if not modules then modules = { } end modules ['node-spl'] = {
- version = 1.001,
- comment = "companion to node-spl.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This module is dedicated to the oriental tex project and for
--- the moment is too experimental to be publicly supported.
---
--- We could cache solutions: say that we store the featureset and
--- all 'words' -> replacement ... so we create a large solution
--- database (per font)
---
--- This module can be optimized by using a dedicated dynamics handler
--- but I'll only do that when the rest of the code is stable.
---
--- Todo: bind setups to paragraph.
-
-local gmatch, concat, format, remove = string.gmatch, table.concat, string.format, table.remove
-local next, tostring, tonumber = next, tostring, tonumber
-local utfchar = utf.char
-local random = math.random
-
-local trace_split = false trackers.register("builders.paragraphs.solutions.splitters.splitter", function(v) trace_split = v end)
-local trace_optimize = false trackers.register("builders.paragraphs.solutions.splitters.optimizer", function(v) trace_optimize = v end)
-local trace_colors = false trackers.register("builders.paragraphs.solutions.splitters.colors", function(v) trace_colors = v end)
-local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end)
-
-local report_solutions = logs.reporter("fonts","solutions")
-local report_splitters = logs.reporter("nodes","splitters")
-local report_optimizers = logs.reporter("nodes","optimizers")
-
-local nodes, node = nodes, node
-
-local variables = interfaces.variables
-
-local settings_to_array = utilities.parsers.settings_to_array
-local settings_to_hash = utilities.parsers.settings_to_hash
-
-local find_node_tail = node.tail or node.slide
-local free_node = node.free
-local free_nodelist = node.flush_list
-local has_attribute = node.has_attribute
-local set_attribute = node.set_attribute
-local new_node = node.new
-local copy_node = node.copy
-local copy_nodelist = node.copy_list
-local traverse_nodes = node.traverse
-local traverse_ids = node.traverse_id
-local protect_glyphs = nodes.handlers.protectglyphs or node.protect_glyphs
-local hpack_nodes = node.hpack
-local insert_node_before = node.insert_before
-local insert_node_after = node.insert_after
-local repack_hlist = nodes.repackhlist
-
-local setnodecolor = nodes.tracers.colors.set
-
-local nodecodes = nodes.nodecodes
-local whatsitcodes = nodes.whatsitcodes
-
-local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local hlist_code = nodecodes.hlist
-local whatsit_code = nodecodes.whatsit
-
-local localpar_code = whatsitcodes.localpar
-local dir_code = whatsitcodes.dir
-local userdefined_code = whatsitcodes.userdefined
-
-local nodepool = nodes.pool
-local tasks = nodes.tasks
-local usernodeids = nodepool.userids
-
-local new_textdir = nodepool.textdir
-local new_usernumber = nodepool.usernumber
-
-local starttiming = statistics.starttiming
-local stoptiming = statistics.stoptiming
-local process_characters = nodes.handlers.characters
-local inject_kerns = nodes.injections.handler
-local fontdata = fonts.hashes.identifiers
-local setfontdynamics = fonts.hashes.setdynamics
-local fontprocesses = fonts.hashes.processes
-
-local parbuilders = builders.paragraphs
-parbuilders.solutions = parbuilders.solutions or { }
-parbuilders.solutions.splitters = parbuilders.solutions.splitters or { }
-
-local splitters = parbuilders.solutions.splitters
-
-local preroll = true
-local variant = "normal"
-local split = attributes.private('splitter')
-local cache = { }
-local solutions = { } -- attribute sets
-local variants = { }
-local max_less = 0
-local max_more = 0
-local criterium = 0
-local randomseed = nil
-local optimize = nil -- set later
-
-function splitters.setup(setups)
- local method = settings_to_hash(setups.method or "")
- if method[variables.preroll] then
- preroll = true
- else
- preroll = false
- end
- for k, v in next, method do
- if variants[k] then
- optimize = variants[k]
- end
- end
- randomseed = tonumber(setups.randomseed)
- criterium = tonumber(setups.criterium) or criterium
-end
-
-local contextsetups = fonts.specifiers.contextsetups
-
-local function convert(featuresets,name,set,what)
- local list, numbers, nofnumbers = set[what], { }, 0
- if list then
- for i=1,#list do
- local feature = list[i]
- local fs = featuresets[feature]
- local fn = fs and fs.number
- if not fn then
- -- fall back on global features
- fs = contextsetups[feature]
- fn = fs and fs.number
- end
- if fn then
- nofnumbers = nofnumbers + 1
- numbers[nofnumbers] = fn
- if trace_goodies or trace_optimize then
- report_solutions("solution %s of '%s' uses feature '%s' with number %s",i,name,feature,fn)
- end
- else
- report_solutions("solution %s has an invalid feature reference '%s'",i,name,tostring(feature))
- end
- end
- return nofnumbers > 0 and numbers
- end
-end
-
-local function initialize(goodies)
- local solutions = goodies.solutions
- if solutions then
- local featuresets = goodies.featuresets
- local goodiesname = goodies.name
- if trace_goodies or trace_optimize then
- report_solutions("checking solutions in '%s'",goodiesname)
- end
- for name, set in next, solutions do
- set.less = convert(featuresets,name,set,"less")
- set.more = convert(featuresets,name,set,"more")
- end
- end
-end
-
-fonts.goodies.register("solutions",initialize)
-
-function splitters.define(name,parameters)
- local settings = settings_to_hash(parameters) -- todo: interfacing
- local goodies, solution, less, more = settings.goodies, settings.solution, settings.less, settings.more
- local less_set, more_set
- local l = less and settings_to_array(less)
- local m = more and settings_to_array(more)
- if goodies then
- goodies = fonts.goodies.load(goodies) -- also in tfmdata
- if goodies then
- local featuresets = goodies.featuresets
- local solution = solution and goodies.solutions[solution]
- if l and #l > 0 then
- less_set = convert(featuresets,name,settings,"less") -- take from settings
- else
- less_set = solution and solution.less -- take from goodies
- end
- if m and #m > 0 then
- more_set = convert(featuresets,name,settings,"more") -- take from settings
- else
- more_set = solution and solution.more -- take from goodies
- end
- end
- else
- if l then
- local n = #less_set
- for i=1,#l do
- local ss = contextsetups[l[i]]
- if ss then
- n = n + 1
- less_set[n] = ss.number
- end
- end
- end
- if m then
- local n = #more_set
- for i=1,#m do
- local ss = contextsetups[m[i]]
- if ss then
- n = n + 1
- more_set[n] = ss.number
- end
- end
- end
- end
- if trace_optimize then
- report_solutions("defining solutions '%s', less: '%s', more: '%s'",name,concat(less_set or {}," "),concat(more_set or {}," "))
- end
- local nofsolutions = #solutions + 1
- solutions[nofsolutions] = {
- solution = solution,
- less = less_set or { },
- more = more_set or { },
- settings = settings, -- for tracing
- }
- context(nofsolutions)
-end
-
-local nofwords, noftries, nofadapted, nofkept, nofparagraphs = 0, 0, 0, 0, 0
-
-local splitter_one = usernodeids["splitters.one"]
-local splitter_two = usernodeids["splitters.two"]
-
-function splitters.split(head)
- -- quite fast
- local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0
- cache, max_less, max_more = { }, 0, 0
- local function flush() -- we can move this
- local font = start.font
- local last = stop.next
- local list = last and copy_nodelist(start,last) or copy_nodelist(start)
- local n = #cache + 1
- local user_one = new_usernumber(splitter_one,n)
- local user_two = new_usernumber(splitter_two,n)
- head, start = insert_node_before(head,start,user_one)
- insert_node_after(head,stop,user_two)
- if rlmode == "TRT" or rlmode == "+TRT" then
- local dirnode = new_textdir("+TRT")
- list.prev = dirnode
- dirnode.next = list
- list = dirnode
- end
- local c = {
- original = list,
- attribute = attribute,
- direction = rlmode,
- font = font
- }
- if trace_split then
- report_splitters("cached %4i: font: %s, attribute: %s, word: %s, direction: %s", n,
- font, attribute, nodes.listtoutf(list,true), rlmode)
- end
- cache[n] = c
- local solution = solutions[attribute]
- local l, m = #solution.less, #solution.more
- if l > max_less then max_less = l end
- if m > max_more then max_more = m end
- start, stop, done = nil, nil, true
- end
- while current do
- local id = current.id
- if id == glyph_code and current.subtype < 256 then
- local a = has_attribute(current,split)
- if not a then
- start, stop = nil, nil
- elseif not start then
- start, stop, attribute = current, current, a
- elseif a ~= attribute then
- start, stop = nil, nil
- else
- stop = current
- end
- current = current.next
- elseif id == disc_code then
- start, stop, current = nil, nil, current.next
- elseif id == whatsit_code then
- if start then
- flush()
- end
- local subtype = current.subtype
- if subtype == dir_code or subtype == localpar_code then
- rlmode = current.dir
- end
- current = current.next
- else
- if start then
- flush()
- end
- current = current.next
- end
- end
- if start then
- flush()
- end
- nofparagraphs = nofparagraphs + 1
- nofwords = nofwords + #cache
- return head, done
-end
-
-local function collect_words(list)
- local words, w, word = { }, 0, nil
- for current in traverse_ids(whatsit_code,list) do
- if current.subtype == userdefined_code then
- local user_id = current.user_id
- if user_id == splitter_one then
- word = { current.value, current, current }
- w = w + 1
- words[w] = word
- elseif user_id == splitter_two then
- word[3] = current
- end
- end
- end
- return words -- check for empty (elsewhere)
-end
-
--- we could avoid a hpack but hpack is not that slow
-
-local function doit(word,list,best,width,badness,line,set,listdir)
- local changed = 0
- local n = word[1]
- local found = cache[n]
- if found then
- local original, attribute, direction = found.original, found.attribute, found.direction
- local solution = solutions[attribute]
- local features = solution and solution[set]
- if features then
- local featurenumber = features[best] -- not ok probably
- if featurenumber then
- noftries = noftries + 1
- local first = copy_nodelist(original)
- if not trace_colors then
- for n in traverse_nodes(first) do -- maybe fast force so no attr needed
- set_attribute(n,0,featurenumber) -- this forces dynamics
- end
- elseif set == "less" then
- for n in traverse_nodes(first) do
- setnodecolor(n,"font:isol")
- set_attribute(n,0,featurenumber)
- end
- else
- for n in traverse_nodes(first) do
- setnodecolor(n,"font:medi")
- set_attribute(n,0,featurenumber)
- end
- end
- local font = found.font
- -- local dynamics = found.dynamics
- -- local shared = fontdata[font].shared
- -- if not dynamics then -- we cache this
- -- dynamics = shared.dynamics
- -- found.dynamics = dynamics
- -- end
- -- local processors = found[featurenumber]
- -- if not processors then -- we cache this too
- -- processors = fonts.handlers.otf.setdynamics(font,featurenumber)
- -- found[featurenumber] = processors
- -- end
- local setdynamics = setfontdynamics[font]
- if setdynamics then
- local processes = setdynamics(font,featurenumber)
- for i=1,#processes do -- often more than 1
- first = processes[i](first,font,featurenumber)
- end
- else
- report_solutions("fatal error, no dynamics for font %s",font)
- end
- first = inject_kerns(first)
- local h = word[2].next -- head of current word
- local t = word[3].prev -- tail of current word
- if first.id == whatsit_code then
- local temp = first
- first = first.next
- free_node(temp)
- end
- local last = find_node_tail(first)
- -- replace [u]h->t by [u]first->last
- local next, prev = t.next, h.prev
- prev.next, first.prev = first, prev
- if next then
- last.next, next.prev = next, last
- end
- -- check new pack
- local temp, b = repack_hlist(list,width,'exactly',listdir)
- if b > badness then
- if trace_optimize then
- report_optimizers("line %s, badness before: %s, after: %s, criterium: %s -> quit",line,badness,b,criterium)
- end
- -- remove last insert
- prev.next, h.prev = h, prev
- if next then
- t.next, next.prev = next, t
- else
- t.next = nil
- end
- last.next = nil
- free_nodelist(first)
- else
- if trace_optimize then
- report_optimizers("line %s, badness before: %s, after: %s, criterium: %s -> continue",line,badness,b,criterium)
- end
- -- free old h->t
- t.next = nil
- free_nodelist(h)
- changed, badness = changed + 1, b
- end
- if b <= criterium then
- return true, changed
- end
- end
- end
- end
- return false, changed
-end
-
--- We repeat some code but adding yet another layer of indirectness is not
--- making things better.
-
-variants[variables.normal] = function(words,list,best,width,badness,line,set,listdir)
- local changed = 0
- for i=1,#words do
- local done, c = doit(words[i],list,best,width,badness,line,set,listdir)
- changed = changed + c
- if done then
- break
- end
- end
- if changed > 0 then
- nofadapted = nofadapted + 1
- -- todo: get rid of pack when ok because we already have packed and we only need the last b
- local list, b = repack_hlist(list,width,'exactly',listdir)
- return list, true, changed, b -- badness
- else
- nofkept = nofkept + 1
- return list, false, 0, badness
- end
-end
-
-variants[variables.reverse] = function(words,list,best,width,badness,line,set,listdir)
- local changed = 0
- for i=#words,1,-1 do
- local done, c = doit(words[i],list,best,width,badness,line,set,listdir)
- changed = changed + c
- if done then
- break
- end
- end
- if changed > 0 then
- nofadapted = nofadapted + 1
- -- todo: get rid of pack when ok because we already have packed and we only need the last b
- local list, b = repack_hlist(list,width,'exactly',listdir)
- return list, true, changed, b -- badness
- else
- nofkept = nofkept + 1
- return list, false, 0, badness
- end
-end
-
-variants[variables.random] = function(words,list,best,width,badness,line,set,listdir)
- local changed = 0
- while #words > 0 do
- local done, c = doit(remove(words,random(1,#words)),list,best,width,badness,line,set,listdir)
- changed = changed + c
- if done then
- break
- end
- end
- if changed > 0 then
- nofadapted = nofadapted + 1
- -- todo: get rid of pack when ok because we already have packed and we only need the last b
- local list, b = repack_hlist(list,width,'exactly',listdir)
- return list, true, changed, b -- badness
- else
- nofkept = nofkept + 1
- return list, false, 0, badness
- end
-end
-
-optimize = variants.normal -- the default
-
-local function show_quality(current,what,line)
- local set = current.glue_set
- local sign = current.glue_sign
- local order = current.glue_order
- local amount = set * ((sign == 2 and -1) or 1)
- report_optimizers("line %s, %s, amount %s, set %s, sign %s (%s), order %s",line,what,amount,set,sign,how,order)
-end
-
-function splitters.optimize(head)
- local nc = #cache
- if nc > 0 then
- starttiming(splitters)
- local listdir = nil -- todo ! ! !
- if randomseed then
- math.setrandomseedi(randomseed)
- randomseed = nil
- end
- local line = 0
- local tex_hbadness, tex_hfuzz = tex.hbadness, tex.hfuzz
- tex.hbadness, tex.hfuzz = 10000, number.maxdimen
- if trace_optimize then
- report_optimizers("preroll: %s, variant: %s, preroll criterium: %s, cache size: %s",
- tostring(preroll),variant,criterium,nc)
- end
- for current in traverse_ids(hlist_code,head) do
- -- report_splitters("before: [%s] => %s",current.dir,nodes.tosequence(current.list,nil))
- line = line + 1
- local sign, dir, list, width = current.glue_sign, current.dir, current.list, current.width
- local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node
- if badness > 0 then
- if sign == 0 then
- if trace_optimize then
- report_optimizers("line %s, badness %s, okay",line,badness)
- end
- else
- local set, max
- if sign == 1 then
- if trace_optimize then
- report_optimizers("line %s, badness %s, underfull, trying more",line,badness)
- end
- set, max = "more", max_more
- else
- if trace_optimize then
- report_optimizers("line %s, badness %s, overfull, trying less",line,badness)
- end
- set, max = "less", max_less
- end
- -- we can keep the best variants
- local lastbest, lastbadness = nil, badness
- if preroll then
- local bb, base
- for i=1,max do
- if base then
- free_nodelist(base)
- end
- base = copy_nodelist(list)
- local words = collect_words(base) -- beware: words is adapted
- for j=i,max do
- local temp, done, changes, b = optimize(words,base,j,width,badness,line,set,dir)
- base = temp
- if trace_optimize then
- report_optimizers("line %s, alternative: %s.%s, changes: %s, badness %s",line,i,j,changes,b)
- end
- bb = b
- if b <= criterium then
- break
- end
- -- if done then
- -- break
- -- end
- end
- if bb and bb > criterium then -- needs checking
- if not lastbest then
- lastbest, lastbadness = i, bb
- elseif bb > lastbadness then
- lastbest, lastbadness = i, bb
- end
- else
- break
- end
- end
- free_nodelist(base)
- end
- local words = collect_words(list)
- for best=lastbest or 1,max do
- local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir)
- current.list = temp
- if trace_optimize then
- report_optimizers("line %s, alternative: %s, changes: %s, badness %s",line,best,changes,b)
- end
- if done then
- if b <= criterium then -- was == 0
- protect_glyphs(list)
- break
- end
- end
- end
- end
- else
- if trace_optimize then
- report_optimizers("line %s, not bad enough",line)
- end
- end
- -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus
- current.list = hpack_nodes(current.list,width,'exactly',listdir)
- -- report_splitters("after: [%s] => %s",temp.dir,nodes.tosequence(temp.list,nil))
- end
- for i=1,nc do
- local ci = cache[i]
- free_nodelist(ci.original)
- end
- cache = { }
- tex.hbadness, tex.hfuzz = tex_hbadness, tex_hfuzz
- stoptiming(splitters)
- end
-end
-
-statistics.register("optimizer statistics", function()
- if nofwords > 0 then
- local elapsed = statistics.elapsedtime(splitters)
- local average = noftries/elapsed
- return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %0.3f seconds used, %s adapted, %0.1f lines per second",
- nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average)
- end
-end)
-
-function splitters.enable()
- tasks.enableaction("processors", "builders.paragraphs.solutions.splitters.split")
- tasks.enableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
-end
-
-function splitters.disable()
- tasks.disableaction("processors", "builders.paragraphs.solutions.splitters.split")
- tasks.disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
-end
diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua
index 70e4639b8..6b5f49964 100644
--- a/tex/context/base/node-tra.lua
+++ b/tex/context/base/node-tra.lua
@@ -46,6 +46,7 @@ local copy_node_list = node.copy_list
local hpack_node_list = node.hpack
local free_node_list = node.flush_list
local traverse_nodes = node.traverse
+local traverse_by_id = node.traverse_id
local nodecodes = nodes.nodecodes
local whatcodes = nodes.whatcodes
@@ -219,7 +220,7 @@ function step_tracers.nofsteps()
return context(#collection)
end
-function step_tracers.glyphs(n,i)
+function step_tracers.glyphs(n,i) -- no need for hpack
local c = collection[i]
if c then
tex.box[n] = hpack_node_list(copy_node_list(c))
@@ -352,7 +353,7 @@ end
function nodes.handlers.checkglyphs(head,message)
local t = { }
- for g in traverse_id(glyph_code,head) do
+ for g in traverse_by_id(glyph_code,head) do
t[#t+1] = format("U+%04X:%s",g.char,g.subtype)
end
if #t > 0 then
@@ -539,7 +540,7 @@ end
nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end
-local function listtoutf(h,joiner,textonly)
+local function listtoutf(h,joiner,textonly,last)
local joiner = (joiner == true and utfchar(0x200C)) or joiner -- zwnj
local w = { }
while h do
@@ -557,13 +558,17 @@ local function listtoutf(h,joiner,textonly)
mid and listtoutf(mid,joiner,textonly) or ""
)
elseif textonly then
- if id == glue_code and h.width > 0 then
+ if id == glue_code and h.spec and h.spec.width > 0 then
w[#w+1] = " "
end
else
w[#w+1] = "[-]"
end
- h = h.next
+ if h == last then
+ break
+ else
+ h = h.next
+ end
end
return concat(w)
end
@@ -710,22 +715,79 @@ local get_attribute = node.has_attribute
local set_attribute = node.set_attribute
local unset_attribute = node.unset_attribute
-local attribute = attributes.private('color')
-local colormodel = attributes.private('colormodel')
-local mapping = attributes.list[attribute] or { }
+local a_color = attributes.private('color')
+local a_colormodel = attributes.private('colormodel')
+local a_state = attributes.private('state')
+local m_color = attributes.list[a_color] or { }
function colors.set(n,c,s)
- local mc = mapping[c]
+ local mc = m_color[c]
if not mc then
- unset_attribute(n,attribute)
+ unset_attribute(n,a_color)
else
- if not get_attribute(n,colormodel) then
- set_attribute(n,colormodel,s or 1)
+ if not get_attribute(n,a_colormodel) then
+ set_attribute(n,a_colormodel,s or 1)
+ end
+ set_attribute(n,a_color,mc)
+ end
+end
+
+function colors.setlist(n,c,s)
+ while n do
+ local mc = m_color[c]
+ if not mc then
+ unset_attribute(n,a_color)
+ else
+ if not get_attribute(n,a_colormodel) then
+ set_attribute(n,a_colormodel,s or 1)
+ end
+ set_attribute(n,a_color,mc)
end
- set_attribute(n,attribute,mc)
+ n = n.next
end
end
function colors.reset(n)
- unset_attribute(n,attribute)
+ unset_attribute(n,a_color)
+end
+
+-- maybe
+
+local transparencies = { }
+tracers.transparencies = transparencies
+
+local a_transparency = attributes.private('transparency')
+local m_transparency = attributes.list[a_transparency] or { }
+
+function transparencies.set(n,t)
+ local mt = m_transparency[t]
+ if not mt then
+ unset_attribute(n,a_transparency)
+ else
+ set_attribute(n,a_transparency,mt)
+ end
+end
+
+function transparencies.setlist(n,c,s)
+ while n do
+ local mt = m_transparency[c]
+ if not mt then
+ unset_attribute(n,a_transparency)
+ else
+ set_attribute(n,a_transparency,mt)
+ end
+ n = n.next
+ end
+end
+
+function transparencies.reset(n)
+ unset_attribute(n,a_transparency)
+end
+
+-- for the moment here
+
+nodes.visualizers = { }
+
+function nodes.visualizers.handler(head)
+ return head, false
end
diff --git a/tex/context/base/node-tsk.lua b/tex/context/base/node-tsk.lua
index efc51913c..ccaa6c6b4 100644
--- a/tex/context/base/node-tsk.lua
+++ b/tex/context/base/node-tsk.lua
@@ -14,9 +14,9 @@ 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 report_tasks = logs.reporter("tasks")
-local allocate = utilities.storage.allocate
+local allocate = utilities.storage.allocate
local nodes = nodes
diff --git a/tex/context/base/node-typ.lua b/tex/context/base/node-typ.lua
index 5f8df2b44..754b398c4 100644
--- a/tex/context/base/node-typ.lua
+++ b/tex/context/base/node-typ.lua
@@ -13,6 +13,7 @@ local fontparameters = fonts.hashes.parameters
local hpack = node.hpack
local vpack = node.vpack
+local fast_hpack = nodes.fasthpack
local nodepool = nodes.pool
@@ -45,7 +46,9 @@ local function tonodes(str,fontid,spacing) -- quick and dirty
next = newglyph(fontid or 1,c)
spacedone = false
end
- if not head then
+ if not next then
+ -- nothing
+ elseif not head then
head = next
else
prev.next = next
@@ -62,6 +65,10 @@ function typesetters.hpack(str,fontid,spacing)
return hpack(tonodes(str,fontid,spacing),"exactly")
end
+function typesetters.fast_hpack(str,fontid,spacing)
+ return fast_hpack(tonodes(str,fontid,spacing),"exactly")
+end
+
function typesetters.vpack(str,fontid,spacing)
-- vpack is just a hack, and a proper implentation is on the agenda
-- as it needs more info etc than currently available
diff --git a/tex/context/base/norm-ctx.mkiv b/tex/context/base/norm-ctx.mkiv
index ff1676743..4b0027332 100644
--- a/tex/context/base/norm-ctx.mkiv
+++ b/tex/context/base/norm-ctx.mkiv
@@ -1,8 +1,8 @@
%D \module
%D [ file=norm-ctx,
%D version=2009.03.19,
-%D title=\CONTEXT\ Norm Macros,
-%D subtitle=\ALEPH\ and \OMEGA,
+%D title=\CONTEXT\ Normal Macros,
+%D subtitle=\CONTEXT,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
@@ -11,8 +11,10 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+\unprotect
+
%D A few more might end up here (like the weird ones in syst-ini).
\let\normalreqno\normaleqno
-\endinput
+\protect \endinput
diff --git a/tex/context/base/pack-bar.mkiv b/tex/context/base/pack-bar.mkiv
index 6967173e2..06eeebd14 100644
--- a/tex/context/base/pack-bar.mkiv
+++ b/tex/context/base/pack-bar.mkiv
@@ -13,55 +13,80 @@
\writestatus{loading}{ConTeXt Packaging Macros / Bars}
-%D This code has been moved from scrn-int to here (was some old
-%D experimental code). It could be in scrn-bar but it's static.
\unprotect
+%D This code has been moved from scrn-int to here (was some old
+%D experimental code). It could be in scrn-bar but it's static. In
+%D the meantime the interface has been adapted to a key|/|value one.
+%D
%D \startbuffer
-%D \dorecurse{10}
-%D {\horizontalpositionbar
-%D \pos\recurselevel \min1 \max10
-%D \token\framed{\recurselevel}%
-%D \\}
+%D \dorecurse{10}{
+%D \ruledhbox{\horizontalpositionbar[n=#1,min=1,max=10,text=!,color=red]}
+%D \par
+%D }
+%D \stopbuffer
+%D
+%D \typebuffer \stoplinecorrection \getbuffer \stoplinecorrection
%D
-%D \hbox to 15em
-%D {\hss
-%D \dorecurse{10}
-%D {\verticalpositionbar\pos\recurselevel\min1\max10\token\blackrule\\
-%D \hss}}
+%D \startbuffer
+%D \dorecurse{10}{
+%D \ruledhbox{\horizontalgrowingbar[n=#1,min=1,max=10,text=!,color=red]}
+%D \par
+%D }
%D \stopbuffer
+%D
+%D \typebuffer \stoplinecorrection \getbuffer \stoplinecorrection
+
+\installcorenamespace{positionbar}
+
+\installsimplecommandhandler \??positionbar {positionbar}
+
+\setuppositionbar
+ [\c!min=1,
+ \c!max=1,
+ \c!n=1,
+ \c!text=?,
+ \c!width=\emwidth,
+ \c!height=\strutheight,
+ \c!depth=\strutdepth]
-\def\horizontalpositionbar\pos#1\min#2\max#3\token#4\\%
+\unexpanded\def\horizontalpositionbar[#1]%
{\hbox to \hsize
- {\hskip\zeropoint\!!plus #1\!!fill
- \hskip\zeropoint\!!plus-#2\!!fill
- #4\relax
- \hskip\zeropoint\!!plus #3\!!fill
- \hskip\zeropoint\!!plus-#1\!!fill}}
+ {\setuppositionbar[#1]%
+ \usepositionbarstyleandcolor\c!style\c!color
+ \hskip\zeropoint\s!plus \positionbarparameter\c!n \s!fill
+ \hskip\zeropoint\s!plus-\positionbarparameter\c!min\s!fill
+ \positionbarparameter\c!text\relax
+ \hskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill
+ \hskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}}
-\def\verticalpositionbar\pos#1\min#2\max#3\token#4\\%
+\unexpanded\def\verticalpositionbar[#1]%
{\vbox to \vsize
- {\vskip\zeropoint\!!plus #1\!!fill
- \vskip\zeropoint\!!plus-#2\!!fill
- \hbox{#4}\relax
- \vskip\zeropoint\!!plus #3\!!fill
- \vskip\zeropoint\!!plus-#1\!!fill}}
+ {\setuppositionbar[#1]%
+ \usepositionbarstyleandcolor\c!style\c!color
+ \vskip\zeropoint\s!plus \positionbarparameter\c!n \s!fill
+ \vskip\zeropoint\s!plus-\positionbarparameter\c!min\s!fill
+ \positionbarparameter\c!text\relax
+ \vskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill
+ \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}}
-\def\horizontalgrowingbar\pos#1\min#2\max#3\height#4\depth#5\\%
+\unexpanded\def\horizontalgrowingbar[#1]%
{\hbox to \hsize
- {\scratchcounter\numexpr#1-#2+\plusone\relax
- \leaders\vrule\hskip\zeropoint\!!plus \scratchcounter\!!fill
- \vrule\!!width\zeropoint\!!height#4\!!depth#5%
- \hskip\zeropoint\!!plus #3\!!fill
- \hskip\zeropoint\!!plus-#1\!!fill}}
+ {\setuppositionbar[#1]%
+ \usepositionbarstyleandcolor\c!style\c!color
+ \leaders\vrule\hskip\zeropoint\s!plus \numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill
+ \vrule\s!width\zeropoint\s!height\positionbarparameter\c!height\s!depth\positionbarparameter\c!depth
+ \hskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill
+ \hskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}}
-\def\verticalgrowingbar\pos#1\min#2\max#3\width#4\\%
+\unexpanded\def\verticalgrowingbar[#1]%
{\vbox to \vsize
- {\scratchcounter\numexpr#1-#2+\plusone\relax
- \leaders\hrule\vskip\zeropoint\!!plus\scratchcounter\!!fill
- \hrule\!!width#4\!!height\zeropoint\!!depth\zeropoint
- \vskip\zeropoint\!!plus #3\!!fill
- \vskip\zeropoint\!!plus-#1\!!fill}}
+ {\setuppositionbar[#1]%
+ \usepositionbarstyleandcolor\c!style\c!color
+ \leaders\hrule\vskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill
+ \hrule\s!width\positionbarparameter\c!width\s!height\zeropoint\s!depth\zeropoint
+ \vskip\zeropoint\s!plus \positionbarparameter\c!max\s!fill
+ \vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}}
\protect \endinput
diff --git a/tex/context/base/pack-bck.mkvi b/tex/context/base/pack-bck.mkvi
index fbe704fab..57d0ee456 100644
--- a/tex/context/base/pack-bck.mkvi
+++ b/tex/context/base/pack-bck.mkvi
@@ -209,7 +209,7 @@
% \c!color=,
% \c!background=\v!screen,
% \c!backgroundcolor=\backgroundparameter\c!color,
-% \c!screen=\@@rsscreen,
+% \c!screen=\defaultbackgroundscreen,
%
\c!background=\v!color,
\c!backgroundcolor=lightgray,
diff --git a/tex/context/base/pack-box.mkiv b/tex/context/base/pack-box.mkiv
index 41a17953b..bcdb93875 100644
--- a/tex/context/base/pack-box.mkiv
+++ b/tex/context/base/pack-box.mkiv
@@ -13,36 +13,24 @@
\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.
-
-% \placeornament
+%D This module contains all kind of macros for moving content around. Many
+%D macros here come from other modules, but depencies made it more clear
+%D to isolate them. We invite users to document the macros. They can be
+%D handy shortcuts for otherwise complex tasks.
\unprotect
-% we need to set the size, else we get dimensions depending
-% on the content, which in itself is ok, but can lead to loops
-% due to rounding errors (happened in demo-obv)
+%D We need to set the size, else we get dimensions depending on the content,
+%D which in itself is ok, but can lead to loops due to rounding errors (happened
+%D in demo-obv).
\definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\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
+\unexpanded\def\internaltextoverlay#1% will become more generic and installable
+ {\startoverlay % i.e. probably an overlay by itself
{\positionregionoverlay\textanchor{\v!text#1}}% see later
{\composedlayer {\v!text#1}}%
\stopoverlay}
@@ -52,75 +40,6 @@
\defineoverlay[\v!text+1][\internaltextoverlay{+1}]
\defineoverlay[\v!text+2][\internaltextoverlay{+2}]
-% to be documented
-
-% \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
@@ -194,7 +113,7 @@
\c!offset=\zeropoint,
#2,#3]
{\setlayer[#1]{\box\b_pack_anchors}}% % #1 uses ovelaywidth/height
- \framed
+ \framed % could be a predefined framed
[\c!background=anchor,
\c!offset=\v!overlay,
\c!frame=\v!off,
@@ -204,157 +123,182 @@
% collectors
-\def\@@collectorbox{@@collectorbox}
+\installcorenamespace{collectorbox}
+\installcorenamespace{collector}
+
+\installcommandhandler \??collector {collector} \??collector
+
+\setupcollector
+ [\c!state=\v!start,
+ \c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!offset=\zeropoint,
+ \c!rotation=, % geen 0 !
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!location=rb,
+ \c!corner=]
+
+\appendtoks
+ \ifcsname\??collectorbox\currentcollector\endcsname \else
+ \expandafter\newbox\csname\??collectorbox\currentcollector\endcsname
+ \fi
+\to \everydefinecollector
-\unexpanded\def\definecollector
- {\dodoubleargument\dodefinecollector}
+\unexpanded\def\resetcollector[#1]%
+ {\ifcsname\??collectorbox#1\endcsname
+ \global\setbox\csname\??collectorbox#1\endcsname\emptybox
+ \fi}
-\def\dodefinecollector[#1][#2]%
- {\ifcsname\@@collectorbox#1\endcsname \else
- \expandafter\newbox\csname\@@collectorbox#1\endcsname
- \fi
- \resetcollector[#1]%
- \setupcollector
- [#1]
- [\c!state=\v!start,
- \c!x=\!!zeropoint,\c!y=\!!zeropoint,
- \c!offset=\!!zeropoint,\c!rotation=, % geen 0 !
- \c!hoffset=\!!zeropoint,\c!voffset=\!!zeropoint,
- \c!location=rb,\c!corner=,#2]}
-
-\unexpanded\def\setupcollector
- {\dodoubleargument\dosetupcollector}
-
-\def\dosetupcollector[#1][#2]%
- {\def\docommand##1{\getparameters[\??cb##1][#2]}%
- \processcommalist[#1]\docommand}
-
-\def\setcollector
- {\dodoubleargument\dosetcollector}
-
-\def\dosetcollector[#1][#2]%
+\newconditional\c_pack_boxes_collector_valid_box
+
+\let\b_pack_boxes_collector\scratchbox
+
+\def\pack_boxes_collector_check_box#1%
+ {\edef\currentcollector{#1}%
+ \ifcsname\??collectorbox\currentcollector\endcsname
+ \settrue\c_pack_boxes_collector_valid_box
+ \expandafter\let\expandafter\b_pack_boxes_collector\csname\??collectorbox\currentcollector\endcsname
+ \else
+ \setfalse\c_pack_boxes_collector_valid_box
+ \writestatus{collector}{unknown collector \currentcollector}%
+ \fi}
+
+\unexpanded\def\setcollector
{\bgroup
- \forgetall
+ \dodoubleargument\pack_boxes_collector}
+
+\def\pack_boxes_collector[#1][#2]% todo: keep reference point
+ {\pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \setupcurrentcollector[#2]
+ \expandafter\pack_boxes_collector_yes
+ \else
+ \expandafter\pack_boxes_collector_nop
+ \fi}
+
+\def\pack_boxes_collector_yes
+ {\forgetall
\dontcomplain
- \dowithnextbox
- {\ifcsname\@@collectorbox#1\endcsname
- \dodosetcollector[#1][#2]%
- \else
- \writestatus{collector}{unknown layer #1}%
- \fi
- \egroup}
- \hbox}
+ \dowithnextboxcs\pack_boxes_collector_finish\hbox}
-\def\collectorparameter#1{\csname\??cb\currentcollector#1\endcsname}
-
-\def\dodosetcollector[#1][#2]% todo: keep reference point
- {\def\currentcollector{#1}%
- \chardef\collectorbox\csname\@@collectorbox#1\endcsname
- \getparameters[\??cb#1][#2]%
- \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\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\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}%
- {\normalexpanded{\noexpand\doifinset{\v!bottom}{\collectorparameter\c!corner}}
- {\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\d_pack_layers_x_size>\zeropoint
- \advance\d_pack_layers_x_position-\d_pack_layers_x_size
- \d_pack_layers_x_position-\d_pack_layers_x_position
- \fi}}%
+\def\pack_boxes_collector_nop
+ {\egroup}
+
+\installcorenamespace{collectorcorners}
+
+\setvalue{\??collectorcorners\v!middle}%
+ {\ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position.5\d_pack_layers_x_size
+ \fi
+ \ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position.5\d_pack_layers_y_size
+ \fi}
+
+\setvalue{\??collectorcorners\v!bottom}%
+ {\ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position-\d_pack_layers_y_size
+ \d_pack_layers_y_position-\d_pack_layers_y_position
+ \fi}
+
+\setvalue{\??collectorcorners\v!right}%
+ {\ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position-\d_pack_layers_x_size
+ \d_pack_layers_x_position-\d_pack_layers_x_position
+ \fi}
+
+\def\pack_boxes_collector_check_corner#1%
+ {\ifcsname\??collectorcorners#1\endcsname
+ \csname\??collectorcorners#1\endcsname
+ \fi}
+
+\def\pack_boxes_collector_finish
+ {\edef\p_collector_rotation{\collectorparameter\c!rotation}%
+ \edef\p_collector_corner {\collectorparameter\c!corner}%
+ \ifx\p_collector_rotation\empty \else
+ \setbox\nextbox\hbox
+ {\rotate
+ [\c!location=\v!high,
+ \c!rotation=\p_collector_rotation]
+ {\box\nextbox}}%
+ \fi
+ \d_pack_layers_x_size\wd\b_pack_boxes_collector
+ \d_pack_layers_y_size\htdp\b_pack_boxes_collector
+ \d_pack_layers_x_position\dimexpr\collectorparameter\c!x+\collectorparameter\c!hoffset\relax
+ \d_pack_layers_y_position\dimexpr\collectorparameter\c!y+\collectorparameter\c!voffset\relax
+ \rawprocesscommacommand[\p_collector_corner]\pack_boxes_collector_check_corner
\setbox\nextbox\hbox
- {\alignedbox[\collectorparameter\c!location]\vbox{\flushnextbox}}%
+ {\alignedbox[\collectorparameter\c!location]\vbox{\box\nextbox}}%
\boxmaxdepth\zeropoint % really needed, nice example
\global\advance\boxhdisplacement\d_pack_layers_x_position
\ifdim\boxhdisplacement<\zeropoint
- \global\setbox\collectorbox\hbox
+ \global\setbox\b_pack_boxes_collector\hbox
{\hskip-\boxhdisplacement
- \box\collectorbox}%
+ \box\b_pack_boxes_collector}%
\fi
\global\advance\boxvdisplacement\d_pack_layers_y_position
\ifdim\boxvdisplacement<\zeropoint
- \global\setbox\collectorbox\hbox
+ \global\setbox\b_pack_boxes_collector\hbox
{\lower-\boxvdisplacement
- \box\collectorbox}%
+ \box\b_pack_boxes_collector}%
\fi
- \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-\d_pack_layers_x_size
- \hskip\d_pack_layers_x_position\relax
- \ifdim\boxhdisplacement<\zeropoint
- \hskip-\boxhdisplacement
- \fi
+ \d_pack_layers_x_size\wd\b_pack_boxes_collector
+ \d_pack_layers_y_size\htdp\b_pack_boxes_collector
+ \global\setbox\b_pack_boxes_collector\hbox
+ {\box\b_pack_boxes_collector
+ \hskip\dimexpr
+ -\d_pack_layers_x_size
+ +\d_pack_layers_x_position
+ \ifdim\boxhdisplacement<\zeropoint
+ -\boxhdisplacement
+ \fi
+ \relax
\lower\d_pack_layers_y_position\hbox
{\ifdim\boxvdisplacement<\zeropoint
- \lower-\boxvdisplacement\flushnextbox
- \else
- \flushnextbox
- \fi}}%
+ \lower-\boxvdisplacement
+ \fi
+ \box\nextbox}}%
% combine height and depth into depth only (later flushed as height)
- \global\setbox\collectorbox\hbox
- {\lower\ht\collectorbox\box\collectorbox}%
+ \global\setbox\b_pack_boxes_collector\hbox
+ {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}%
% just to be sure
- \ifdim\wd\collectorbox<\d_pack_layers_x_size
- \wd\collectorbox\d_pack_layers_x_size
- \fi}
+ \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size
+ \wd\b_pack_boxes_collector\d_pack_layers_x_size
+ \fi
+ \egroup}
-\def\flushcollector[#1]%
- {\ifcsname\@@collectorbox#1\endcsname
- \doifnotvalue{\??cb#1\c!state}\v!stop
- {\vbox
- {\hbox
- {\doifelsevalue{\??cb#1\c!state}\v!repeat
- {\let\next\copy}{\let\next\box}%
- \raise\dp\csname\@@collectorbox#1\endcsname
- \next\csname\@@collectorbox#1\endcsname}}}%
- \else
- \writestatus{collector}{unknown collector #1}%
- \fi}
+\unexpanded\def\flushcollector[#1]%
+ {\bgroup
+ \pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \edef\p_collector_state{\collectorparameter\c!state}%
+ \ifx\p_collector_state\v!stop \else
+ \vbox{\hbox{\raise
+ \dp\b_pack_boxes_collector
+ \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}%
+ \fi
+ \fi
+ \egroup}
-\def\composedcollector#1{\flushcollector[#1]}
+\unexpanded\def\composedcollector#1% no [], handy as argument
+ {\flushcollector[#1]}
-\def\resetcollector[#1]%
- {\ifcsname\@@collectorbox#1\endcsname
- \global\setbox\csname\@@collectorbox#1\endcsname\emptybox
- \fi}
+\unexpanded\def\adaptcollector
+ {\dodoubleargument\pack_boxes_collector_adapt}
-\def\adaptcollector
- {\dodoubleargument\doadaptcollector}
-
-\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
- \getparameters[\??cb#1][\c!voffset=\zeropoint,\c!hoffset=\zeropoint,#2]%
- \scratchdimen\wd\collectorbox
- \advance\scratchdimen\collectorparameter\c!hoffset
- \global\wd\collectorbox\scratchdimen
- \scratchdimen\ht\collectorbox
- \advance\scratchdimen\collectorparameter\c!voffset
- \global\ht\collectorbox\scratchdimen
- \egroup}
+\def\pack_boxes_collector_adapt[#1][#2]% % a typical case where \global\wd looks better in the code
+ {\begingroup
+ \pack_boxes_collector_check_box{#1}%
+ \ifconditional\c_pack_boxes_collector_valid_box
+ \letcollectorparameter\c!voffset\zeropoint
+ \letcollectorparameter\h!voffset\zeropoint
+ \ifsecondargument
+ \setupcurrentcollector[#2]%
+ \fi
+ \global\wd\b_pack_boxes_collector\dimexpr\wd\b_pack_boxes_collector+\collectorparameter\c!hoffset\relax
+ \global\ht\b_pack_boxes_collector\dimexpr\ht\b_pack_boxes_collector+\collectorparameter\c!voffset\relax
+ \fi
+ \endgroup}
%\definecollector[test]
%\setcollector[test]
@@ -368,23 +312,23 @@
\definecollector
[caption]
-\def\collectedtext
- {\dodoubleempty\docollectedtext}
-
-\def\docollectedtext[#1][#2]#3%
+\unexpanded\def\collectedtext % for captions
{\bgroup
- \dowithnextbox
+ \dodoubleempty\pack_boxes_collector_text}
+
+\def\pack_boxes_collector_text[#1][#2]#3%
+ {\dowithnextbox
{\setcollector
[caption]
- {\flushnextbox}%
+ {\box\nextbox}%
\setcollector
[caption][#1]
- {\getparameters[\??du][\c!style=,\c!color=,#2]%
- \dousestyleparameter\@@dustyle
+ {\letdummyparameter\c!style\empty
+ \letdummyparameter\c!color\empty
+ \getdummyparameters[#2]%
+ \dousestyleparameter{\directdummyparameter\c!style}%
\setupinterlinespace
- \framed % watch the special setting of kader/overlay
- [\c!frame=\v!overlay,\c!foregroundcolor=\@@ducolor,\c!foregroundstyle=\@@dustyle,#2]
- {#3}}%
+ \normalexpanded{\framed[\c!foregroundcolor=\directdummyparameter\c!color,\c!foregroundstyle=\directdummyparameter\c!style},\c!frame=\v!overlay,#2]{#3}}%
\composedcollector{caption}%
\egroup}%
\hbox}
@@ -406,51 +350,6 @@
% [frame=on,offset=0pt]
% {gans}
% {\externalfigure[koe][width=3cm]}
-
-% 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}
@@ -531,15 +430,16 @@
% [frame=on,offset=0pt]
% {gans}
% {\externalfigure[koe][width=3cm]}
-
-\def\ornamenttext
- {\dodoubleempty\doornamenttext}
-\def\doornamenttext[#1][#2]%
+\unexpanded\def\ornamenttext
+ {\dodoubleempty\pack_ornament_text}
+
+\def\pack_ornament_text[#1][#2]%
{\bgroup
\doifassignmentelse{#1}
- {\getparameters[\s!dummy][\c!alternative=\v!a,#1]%
- \doifelse\dummyalternative\v!a
+ {\letdummyparameter\c!alternative\v!a
+ \getdummyparameters[#1]%
+ \doifelse{\directdummyparameter\c!alternative}\v!a
{\egroup\collectedtext}%
{\egroup\layeredtext }%
[#1][#2]}%
@@ -549,7 +449,7 @@
{\dotripleempty\dodefineornament}
\def\dodefineornament[#1][#2][#3]%
- {\setvalue{#1}{\doornamenttext[#2][#3]}}
+ {\setuvalue{#1}{\pack_ornament_text[#2][#3]}}
% \defineornament
% [affiliation]
@@ -582,13 +482,12 @@
% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
%
% \affiliation{drawing}{\externalfigure[hakker][width=3cm]}
-
-% pas op: aanpassen aan nieuwe layer hoek ankers en columnset
-\newcount\nofbleeds % per pag
+\newcount\c_pack_boxes_bleeds
+
+\installcorenamespace {bleeding}
-\unexpanded\def\setupbleeding
- {\dodoubleempty\getparameters[\??bg]}
+\installdirectcommandhandler \??bleeding {bleeding} % \??bleeding
\setupbleeding
[\c!location=l,
@@ -597,92 +496,117 @@
\c!height=3cm,
\c!offset=2mm,
\c!page=\v!no,
- \c!voffset=\@@bgoffset,
- \c!hoffset=\@@bgoffset]
+ \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset
+ \c!hoffset=\scratchoffset] % which often saves one resolve
-\unexpanded\def\bleed
- {\dosingleempty\pack_boxes_bleed}
+\def\bleedwidth {\the\hsize} % these are global !
+\def\bleedheight{\the\vsize} % these are global !
-\def\bleedwidth {\the\hsize}%
-\def\bleedheight{\the\vsize}%
+\newconditional\c_pack_boxes_l
+\newconditional\c_pack_boxes_r
+\newconditional\c_pack_boxes_t
+\newconditional\c_pack_boxes_b
-\def\pack_boxes_bleed[#1]#2%
+\unexpanded\def\bleed
{\hbox\bgroup
+ \dosingleempty\pack_boxes_bleed}
+
+\installcorenamespace{bleedinglocation}
+
+\setvalue{\??bleedinglocation t}{\settrue\c_pack_boxes_t\scratchhoffset\zeropoint}
+\setvalue{\??bleedinglocation b}{\settrue\c_pack_boxes_b\scratchhoffset\zeropoint}
+\setvalue{\??bleedinglocation l}{\settrue\c_pack_boxes_l\scratchvoffset\zeropoint}
+\setvalue{\??bleedinglocation r}{\settrue\c_pack_boxes_r\scratchvoffset\zeropoint}
+\setvalue{\??bleedinglocation bl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation lb}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation br}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation rb}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b}
+\setvalue{\??bleedinglocation tl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation lt}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation tr}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t}
+\setvalue{\??bleedinglocation rt}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t}
+
+\def\pack_boxes_bleed[#1]%
+ {\global\advance\c_pack_boxes_bleeds\plusone
+ %
\xdef\bleedwidth {\the\hsize}%
\xdef\bleedheight{\the\vsize}%
- \global\advance\nofbleeds\plusone
- \getparameters[\??bg][#1]%
- \!!doneafalse % left
- \!!donebfalse % right
- \!!donecfalse % top
- \!!donedfalse % bottom
- % replace this part ! todo: default location
- \processaction
- [\@@bglocation]
- [ t=>\!!donectrue\let\@@bghoffset\!!zeropoint,
- b=>\!!donedtrue\let\@@bghoffset\!!zeropoint,
- l=>\!!doneatrue\let\@@bgvoffset\!!zeropoint,
- r=>\!!donebtrue\let\@@bgvoffset\!!zeropoint,
- bl=>\!!doneatrue\!!donedtrue,
- lb=>\!!doneatrue\!!donedtrue,
- br=>\!!donebtrue\!!donedtrue,
- rb=>\!!donebtrue\!!donedtrue,
- tl=>\!!doneatrue\!!donectrue,
- lt=>\!!doneatrue\!!donectrue,
- tr=>\!!donebtrue\!!donectrue,
- rt=>\!!donebtrue\!!donectrue]%
- \doifelse\@@bgstretch\v!yes\donetrue\donefalse
- \scratchdimen\@@bgwidth
- \edef\currentbgposition {\??bg:\number\nofbleeds}%
+ %
+ \edef\currentbgposition {bleed:\number\c_pack_boxes_bleeds}%
\edef\currentpageposition{page:0}% todo: per page
- \ifdone
- \if!!donea
- \advance\scratchdimen\dimexpr \MPx\currentbgposition-\MPx\currentpageposition\relax
- \else\if!!doneb
- \scratchdimen\dimexpr\paperwidth-\MPx\currentbgposition+\MPx\currentpageposition\relax % not checked
- \fi\fi
- \fi
- \advance\scratchdimen\@@bghoffset
- \xdef\bleedwidth{\the\scratchdimen}%
- \scratchdimen\@@bgheight
- \ifdone
- \if!!donec
- \scratchdimen\dimexpr\paperheight-\MPy\currentbgposition+\MPy\currentpageposition\relax % not checked
- \else\if!!doned
- \advance\scratchdimen\dimexpr \MPy\currentbgposition-\MPy\currentpageposition\relax % not checked
- \fi\fi
- \fi
- \advance\scratchdimen\@@bgvoffset
- \xdef\bleedheight{\the\scratchdimen}%
%
- \bgroup
- \hsize\bleedwidth
- \vsize\bleedheight
- \global\setbox\globalscratchbox\hbox{#2}%
- \egroup
- \setbox\scratchbox\box\globalscratchbox
+ \setupcurrentbleeding[#1]%
%
- \doif\@@bgpage\v!yes
- {\setbox\scratchbox\topskippedbox{\box\scratchbox}}%
- \setbox\scratchbox\hbox to \@@bgwidth
- {\if!!donea\hss\fi\box\scratchbox\if!!doneb\hss\fi}%
- \if!!doned
- \setbox\scratchbox\hbox
- {\lower\bleedheight\hbox{\raise\@@bgheight\box\scratchbox}}%
+ \scratchwidth \bleedingparameter\c!width
+ \scratchheight \bleedingparameter\c!height
+ \scratchoffset \bleedingparameter\c!offset
+ \scratchhoffset\bleedingparameter\c!hoffset
+ \scratchvoffset\bleedingparameter\c!voffset
+ %
+ \setfalse\c_pack_boxes_l % left
+ \setfalse\c_pack_boxes_r % right
+ \setfalse\c_pack_boxes_t % top
+ \setfalse\c_pack_boxes_b % bottom
+ %
+ \csname\??bleedinglocation\bleedingparameter\c!location\endcsname
+ %
+ \doifelse{\bleedingparameter\c!stretch}\v!yes\donetrue\donefalse
+ %
+ \xdef\bleedwidth{\dimexpr
+ \ifdone
+ \ifconditional\c_pack_boxes_l
+ \scratchwidth+\MPx\currentbgposition-\MPx\currentpageposition
+ \else\ifconditional\c_pack_boxes_r
+ \paperwidth -\MPx\currentbgposition+\MPx\currentpageposition % not checked
+ \else
+ \scratchwidth
+ \fi\fi
+ \else
+ \scratchwidth
+ \fi+\scratchhoffset}%
+ \xdef\bleedheight{\dimexpr
+ \ifdone
+ \ifconditional\c_pack_boxes_t
+ \paperheight -\MPy\currentbgposition+\MPy\currentpageposition % not checked
+ \else\ifconditional\c_pack_boxes_b
+ \scratchheight+\MPy\currentbgposition-\MPy\currentpageposition % not checked
+ \else
+ \scratchheight
+ \fi\fi
+ \else
+ \scratchheight
+ \fi+\scratchvoffset}%
+ \dowithnextboxcontentcs\pack_boxes_bleed_settings\pack_boxes_bleed_finish\hbox}
+
+\def\pack_boxes_bleed_settings
+ {\hsize\bleedwidth
+ \vsize\bleedheight}
+
+\def\pack_boxes_bleed_finish
+ {\doif{\bleedingparameter\c!page}\v!yes
+ {\setbox\nextbox\topskippedbox{\box\nextbox}}%
+ \setbox\nextbox\hbox to \scratchwidth
+ {\ifconditional\c_pack_boxes_l\hss\fi
+ \box\nextbox
+ \ifconditional\c_pack_boxes_r\hss\fi}%
+ \ifconditional\c_pack_boxes_b
+ \setbox\nextbox\hbox
+ {\lower\bleedheight\hbox{\raise\scratchheight\box\nextbox}}%
\fi
- \wd\scratchbox\@@bgwidth
- \ht\scratchbox\@@bgheight
- \dp\scratchbox\zeropoint
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\zeropoint
\ifdone
- \hpos\currentbgposition{\box\scratchbox}%
+ \hpos\currentbgposition{\box\nextbox}%
\else
- \box\scratchbox
+ \box\nextbox
\fi
\egroup}
-\setupbleeding[\c!stretch=\v!yes]
-
-\defineexternalfigure[bleed][\c!width=\bleedwidth,\c!height=\bleedheight] % should be \v!bleed
+\defineexternalfigure
+ [bleed] % should be \v!bleed
+ [\c!width=\bleedwidth,
+ \c!height=\bleedheight]
% \placefigure[left]{none}
% {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}}
@@ -717,7 +641,7 @@
% tricky: offsets apply to both the layer and the framed; it makes sense to
% only apply the offset to ...
-\def\setlayerframed
+\unexpanded\def\setlayerframed
{\dotripleempty\pack_layers_set_framed}
\def\pack_layers_set_framed
@@ -741,24 +665,22 @@
{\setlayer[#1][#2]%
\normalframedwithsettings[#3]}
-\def\setlayertext
+\unexpanded\def\setlayertext
{\dotripleempty\pack_layers_set_text}
\def\pack_layers_set_text[#1][#2][#3]%
{\bgroup
- \getparameters
- [\??lx]
- [\c!align=,
- \c!width=\hsize,
- \c!color=,
- \c!style=,
- #3]%
+ \letdummyparameter\c!align\empty
+ \letdummyparameter\c!width\hsize
+ \letdummyparameter\c!color\empty
+ \letdummyparameter\c!style\empty
+ \getdummyparameters[#3]%
\dowithnextboxcontent
{\forgetall
- \hsize\@@lxwidth
- \normalexpanded{\setupalign[\@@lxalign]}%
- \dousestyleparameter\@@lxstyle}
- {\setlayer[#1][#2]{\strut\dousecolorparameter\@@lxcolor\flushnextbox}%
+ \hsize\directdummyparameter\c!width
+ \normalexpanded{\setupalign[\directdummyparameter\c!align]}%
+ \dousestyleparameter{\directdummyparameter\c!style}}
+ {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color
\egroup}%
\vtop}
@@ -804,22 +726,6 @@
[\v!middle]
[\c!corner=\v!middle,\c!location=\v!middle]
-% \definelayerpreset
-% [\v!middle\v!top]
-% [\c!location=\v!bottom,\c!hoffset=.5\layerwidth]
-
-% \definelayerpreset
-% [\v!middle\v!bottom]
-% [\c!location=\v!top,\c!hoffset=.5\layerwidth,\c!voffset=\layerheight]
-
-% \definelayerpreset
-% [\v!middle\v!left]
-% [\c!location=\v!right,\c!voffset=.5\layerheight]
-
-% \definelayerpreset
-% [\v!middle\v!right]
-% [\c!location=\v!left,\c!hoffset=\layerwidth,\c!voffset=.5\layerheight]
-
\definelayerpreset
[\v!middle\v!top]
[\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth]
@@ -901,93 +807,133 @@
% left/right/top/bottomoffset -> dimensions change
% x/y | method=fixed -> dimensions don't change
+\installcorenamespace{offsetbox}
+
+\installautocommandhandler \??offsetbox {offsetbox} \??offsetbox
+
+\setupoffsetbox
+ [\c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!width=\wd\nextbox,
+ \c!height=\ht\nextbox,
+ \c!depth=\dp\nextbox,
+ \c!location=,
+ \c!leftoffset=\zeropoint,
+ \c!rightoffset=\zeropoint,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!method=]
+
+\let\setupoffset\setupoffsetbox
+
\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
+\def\pack_boxes_offset_box[#1]%
+ {\bgroup
+ \pack_boxes_offset_check[#1]%
+ \dowithnextboxcs\pack_boxes_offsetfinish}
+
+\def\pack_boxes_offset[#1]%
+ {\bgroup
+ \pack_boxes_offset_check[#1]%
+ \dowithnextboxcs\pack_boxes_offsetfinish\hbox}
+
+\newcount\c_pack_boxes_offset_level
+
+\def\pack_boxes_offset_check
+ {\advance\c_pack_boxes_offset_level\plusone
+ \edef\currentoffsetbox{\the\c_pack_boxes_offset_level}%
+ \checkoffsetboxparent
+ \setupcurrentoffsetbox}
+
+\def\pack_boxes_offsetfinish
+ {\donefalse
+ \scratchxposition \offsetboxparameter\c!x
+ \scratchyposition \offsetboxparameter\c!y
+ \scratchleftoffset \offsetboxparameter\c!leftoffset
+ \scratchrightoffset \offsetboxparameter\c!rightoffset
+ \scratchtopoffset \offsetboxparameter\c!topoffset
+ \scratchbottomoffset\offsetboxparameter\c!bottomoffset
+ \relax % really needed
+ \ifdim\scratchleftoffset =\zeropoint\else\donetrue\fi
+ \ifdim\scratchrightoffset =\zeropoint\else\donetrue\fi
+ \ifdim\scratchtopoffset =\zeropoint\else\donetrue\fi
+ \ifdim\scratchbottomoffset=\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}%
+ \edef\p_method{\offsetboxparameter\c!method}%
+ \ifx\p_method\v!fixed % new
+ \ifdim\scratchleftoffset=\zeropoint
+ \ifdim\scratchrightoffset=\zeropoint \else
+ \scratchxposition-\scratchrightoffset
+ \scratchrightoffset\zeropoint
+ \fi
+ \else
+ \scratchxposition\scratchleftoffset
+ \scratchleftoffset\zeropoint
+ \fi
+ \ifdim\scratchtopoffset=\zeropoint
+ \ifdim\scratchbottomoffset=\zeropoint \else
+ \scratchyposition-\scratchbottomoffset
+ \scratchbottomoffset\zeropoint
+ \fi
+ \else
+ \scratchyposition\scratchtopoffset
+ \scratchtopoffset\zeropoint
+ \fi
+ \donefalse
+ \fi
\fi
\ifdone
\setbox\nextbox\vbox
{\forgetall % already done
\offinterlineskip
- \vskip\@@oxtopoffset
+ \vskip\scratchtopoffset
\hbox
- {\hskip\@@oxleftoffset
+ {\hskip\scratchleftoffset
\box\nextbox
- \hskip\@@oxrightoffset}%
- \vskip\@@oxbottomoffset}%
+ \hskip\scratchrightoffset}%
+ \vskip\scratchbottomoffset}%
\ht\nextbox\htdp\nextbox
\dp\nextbox\zeropoint
\fi
- \freezedimenmacro\@@oxwidth
- \freezedimenmacro\@@oxheight
- \freezedimenmacro\@@oxdepth
+ \scratchwidth \offsetboxparameter\c!width
+ \scratchheight\offsetboxparameter\c!height
+ \scratchdepth \offsetboxparameter\c!depth
+ \edef\p_location{\offsetboxparameter\c!location}%
\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
+ {\hskip\scratchxposition
+ \lower\scratchyposition\hbox
+ {\ifx\p_location\empty
+ \box\nextbox
+ \else
+ \alignedbox[\p_location]\hbox{\box\nextbox}%
+ \fi}}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\scratchdepth
\box\nextbox
\egroup}
+%D \starttyping
+%D \framed[offset=overlay]{\offset[leftoffset=1cm]
+%D {\framed[offset=overlay]{\offset[rightoffset=1cm]
+%D {\externalfigure[koe][width=1cm]}}}}
+%D
+%D \blank
+%D
+%D \framed[offset=overlay]{\offset[leftoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[rightoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[topoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
+%D \framed[offset=overlay]{\offset[bottomoffset=1cm]{\externalfigure[koe][width=5cm]}} \blank
+%D \stoptyping
+
% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid]
%
-% \placefigure[left,none]{}{\offset[leftoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
-% \input tufte
-% \placefigure[left,none]{}{\offset[rightoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
-% \input tufte
-% \placefigure[left,none]{}{\offset[topoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
-% \input tufte
-% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
-% \input tufte
-
-%\ruledhbox{\offsetbox[x=-1cm,y=-1cm,location=c]
-% {\framed[width=4cm,height=4cm]{x}}}
+% \placefigure[left,none]{}{\offset[leftoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[rightoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[topoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
+% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[cow][width=3cm]}} \input tufte
% Some old code:
%
@@ -1020,15 +966,14 @@
\unexpanded\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{}
{\hbox\bgroup
- \getparameters
- [\??ol] % brrr
- [\c!width=\zeropoint,%
- \c!height=\zeropoint,%
- \c!depth=\zeropoint,#1]%
+ \letdummyparameter\c!width \zeropoint
+ \letdummyparameter\c!height\zeropoint
+ \letdummyparameter\c!depth \zeropoint
+ \getdummyparameters[#1]%
\setbox\scratchbox\emptyhbox
- \wd\scratchbox\@@olwidth
- \ht\scratchbox\@@olheight
- \dp\scratchbox\@@oldepth
+ \wd\scratchbox\directdummyparameter\c!width
+ \ht\scratchbox\directdummyparameter\c!height
+ \dp\scratchbox\directdummyparameter\c!depth
\box\scratchbox
\egroup}
@@ -1044,17 +989,17 @@
\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
+ \scratchdimen#2\divide\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advance\scratchnx\plusone\relax
+ \scratchdimen#3\divide\scratchdimen\ht\nextbox\scratchny\scratchdimen\advance\scratchny\plusone\relax
% 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}}%
+ \setbox\nextbox\hbox{\dorecurse\scratchnx{\copy\nextbox}}%
+ \setbox\nextbox\vbox{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
\or % x
- \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
+ \setbox\nextbox\hbox{\dorecurse\scratchnx{\copy\nextbox}}%
\or % y
- \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
+ \setbox\nextbox\vbox{\dorecurse\scratchny{\copy\nextbox\endgraf}}%
\fi
\fi
\ifdim\wd\nextbox>#2\relax
diff --git a/tex/context/base/pack-com.mkiv b/tex/context/base/pack-com.mkiv
index 4d50bf7c7..fbc2b2732 100644
--- a/tex/context/base/pack-com.mkiv
+++ b/tex/context/base/pack-com.mkiv
@@ -210,7 +210,7 @@
\alignmark\alignmark
\m_pack_combinations_rightfiller
\aligntab
- \tabskip\zeropoint \!!plus 1fill
+ \tabskip\zeropoint \s!plus 1fill
\alignmark\alignmark
\cr
\pack_combinations_pickup}
@@ -663,8 +663,8 @@
\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}
+ \let\pack_pairedboxes_align_t\vss
+ \let\pack_pairedboxes_align_b\vss}
\setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }}
\setvalue{\??pairedboxalign \v!top}{\getvalue{\??pairedboxalign\v!high}}
@@ -789,10 +789,10 @@
\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_one{\bgroup\setbox0\box\nextbox\dowithnextboxcs\pack_topofeachother_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}
+\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/tex/context/base/pack-cut.mkiv b/tex/context/base/pack-cut.mkiv
new file mode 100644
index 000000000..63f4524a8
--- /dev/null
+++ b/tex/context/base/pack-cut.mkiv
@@ -0,0 +1,163 @@
+%D \module
+%D [ file=pack-cut, % comes from core-vis/trac-vis
+%D version=1996.06.01,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Cut boxes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+%D \macros
+%D {makecutbox, cuthbox, cutvbox, cutvtop}
+%D
+%D Although mainly used for marking the page, these macros can
+%D also serve local use.
+%D
+%D \startbuffer
+%D \setbox0=\vbox{a real \crlf vertical box} \makecutbox0
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This marked \type{\vbox} shows up as:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D The alternative macros are used as:
+%D
+%D \startbuffer
+%D \cuthbox{a made cut box}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This is typeset as:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D By setting the next macros one can influence the length of
+%D the marks as well as the horizontal and vertical divisions.
+
+\newdimen\d_pack_cutmarks_width
+\newdimen\d_pack_cutmarks_height
+\newdimen\d_pack_cutmarks_depth
+
+\newcount\horizontalcutmarks \horizontalcutmarks \plustwo
+\newcount\verticalcutmarks \verticalcutmarks \plustwo
+\newcount\cutmarkoffset \cutmarkoffset \plusone
+
+\let\cutmarksymbol \relax
+\let\cutmarktoptext \empty
+\let\cutmarkbottomtext \empty
+\let\cutmarkhoffset \empty
+\let\cutmarkvoffset \empty
+\def\cutmarklength {2\bodyfontsize}
+\def\cutmarkrulethickness{\onepoint}
+
+\unexpanded\def\horizontalcuts
+ {\normalhbox to \d_pack_cutmarks_width
+ {\dorecurse\horizontalcutmarks{\vrule\s!width\cutmarkrulethickness\s!height\cutmarklength\normalhfill}%
+ \unskip}}
+
+\unexpanded\def\verticalcuts
+ {\normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax
+ {\hsize\cutmarklength
+ \dorecurse\verticalcutmarks{\vrule\s!height\cutmarkrulethickness\s!width\hsize\normalvfill}%
+ \unskip}}
+
+\unexpanded\def\baselinecuts
+ {\ifdim\d_pack_cutmarks_depth>\zeropoint
+ \normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax
+ {\hsize\dimexpr\cutmarklength/2\relax
+ \normalvskip\zeropoint\s!plus\d_pack_cutmarks_height
+ \vrule\s!height\cutmarkrulethickness\s!width\hsize
+ \normalvskip\zeropoint\s!plus\d_pack_cutmarks_depth}%
+ \fi}
+
+\unexpanded\def\cutmarksymbols#1%
+ {\normalhbox to \d_pack_cutmarks_width
+ {\setbox\scratchbox\normalhbox to \cutmarklength
+ {\normalhss\infofont\cutmarksymbol\normalhss}%
+ \normalhss
+ \normalvbox to \cutmarklength
+ {\scratchdimen\dimexpr\cutmarklength/2\relax
+ \scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
+ \normalvss
+ \hbox to \d_pack_cutmarks_width
+ {\llap{\copy\scratchbox\normalhskip\scratchskip}%
+ \normalhskip\scratchdimen\hss\infofont#1\hss\normalhskip\scratchdimen
+ \rlap{\normalhskip\scratchskip\copy\scratchbox}}%
+ \normalvss}%
+ \normalhss}}
+
+\unexpanded\def\makecutbox#1%
+ {\bgroup
+ \d_pack_cutmarks_height\ht#1%
+ \d_pack_cutmarks_depth \dp#1%
+ \d_pack_cutmarks_width \wd#1%
+ \setbox#1\normalhbox
+ {\dontcomplain
+ \forgetall
+ \boxmaxdepth\maxdimen
+ \offinterlineskip
+ \scratchdimen\dimexpr\cutmarklength/2\relax
+ \hsize\d_pack_cutmarks_width
+ \setbox\scratchbox\normalvbox
+ {\setbox\scratchbox\normalhbox{\horizontalcuts}%
+ \scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
+ \tlap{\copy\scratchbox\normalvskip\scratchskip}%
+ \hbox to \d_pack_cutmarks_width
+ {\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
+ \setbox\scratchbox\normalhbox{\verticalcuts}%
+ \llap{\copy\scratchbox\normalhskip\scratchskip}%
+ \ifdim\d_pack_cutmarks_depth=\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}}%
+ \blap{\normalvskip\scratchskip\copy\scratchbox}}%
+ \ht\scratchbox\d_pack_cutmarks_height
+ \dp\scratchbox\d_pack_cutmarks_depth
+ \wd\scratchbox\zeropoint
+ \startcolor[\defaulttextcolor]%
+ \box\scratchbox
+ \ifx\cutmarksymbol\relax \else
+ \setbox\scratchbox\normalvbox
+ {\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
+ \vskip-\dimexpr\scratchskip+\cutmarklength\relax
+ \normalhbox{\cutmarksymbols\cutmarktoptext}%
+ \vskip\dimexpr\scratchskip+\d_pack_cutmarks_height+\d_pack_cutmarks_depth+\scratchskip\relax
+ \normalhbox{\cutmarksymbols\cutmarkbottomtext}}%
+ \ht\scratchbox\d_pack_cutmarks_height
+ \dp\scratchbox\d_pack_cutmarks_depth
+ \wd\scratchbox\zeropoint
+ \box\scratchbox
+ \fi
+ \stopcolor
+ \box#1}%
+ \wd#1\d_pack_cutmarks_width
+ \ht#1\d_pack_cutmarks_height
+ \dp#1\d_pack_cutmarks_depth
+ \egroup}
+
+\unexpanded\def\cuthbox{\normalhbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalhbox}
+\unexpanded\def\cutvbox{\normalvbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvbox}
+\unexpanded\def\cutvtop{\normalvtop\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvtop}
+
+\protect \endinput
diff --git a/tex/context/base/pack-mrl.mkiv b/tex/context/base/pack-mrl.mkiv
index f3f3d11d9..ec214d4f3 100644
--- a/tex/context/base/pack-mrl.mkiv
+++ b/tex/context/base/pack-mrl.mkiv
@@ -13,26 +13,24 @@
\writestatus{loading}{ConTeXt Packaging Macros / More Rules}
-%D This module needs an overhaul.
+%D The (re)implementation of margin rules has been moved elsewhere.
\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 The graphic capabilities of \TEX\ do not go beyond simple filled rules, except of
+%D course when using specials or, in \MKIV, manipulate node lists. Let's start with
+%D a warning: using this commands is far more slower than using the \TEX\ primitives
+%D \type {\hrule} and \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 The simple command draws only one rule. Its optional argument can be used to
+%D specify the dimensions. By setting the width, height or depth to \type {max}, one
+%D gets the natural dimensions.
%D
%D \showsetup{blackrule}
@@ -59,9 +57,9 @@
\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
+ \s!width \ifx\p_width \v!max\emwidth\else\p_width \fi
+ \s!height\ifx\p_height\v!max\strutht\else\p_height\fi
+ \s!depth \ifx\p_depth \v!max\strutdp\else\p_depth \fi
\egroup}
\setupblackrules
@@ -73,8 +71,8 @@
%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 One can call for a sequence of black rules, if needed equally spaced over the
+%D given width.
%D
%D \showsetup{blackrules}
%D
@@ -93,9 +91,8 @@
%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.
+%D We could of course have implemented this macro using \type {\leaders}, but this
+%D would probably have taken more tokens.
\unexpanded\def\blackrules % probably never used
{\hbox\bgroup
@@ -122,9 +119,9 @@
\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
+ \s!width \scratchwidth
+ \s!height\scratchheight
+ \s!depth \scratchdepth
\hskip\scratchdistance}%
\unskip
\egroup}
@@ -135,169 +132,51 @@
\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 The command \type {\vl} draws a vertical rule \vl\ with strut dimensions,
+%D multiplied with the factor specified in the optional argument. The height and
+%D depth are clipped \vl [3] to the baselinedistance. Its horizontal counterpart
+%D \type {\hl} draws a horizontal rule \hl\ with a width of 1em, multiplied with the
+%D optional factor. The horizontal rule is drawn on top of the baseline.
%D
%D \showsetup{vl}
%D \showsetup{hl}
-\unexpanded\def\dovlwdhtdp#1#2#3% used elsewhere
+\unexpanded\def\pack_rule_vl_indeed#1#2#3%
{\bgroup
\setbox\scratchbox\hbox
{\vrule
- \!!width #1\linewidth
- \!!height#2\strutht
- \!!depth #3\strutdp}%
+ \s!width #1\linewidth
+ \s!height#2\strutht
+ \s!depth #3\strutdp}%
\dp\scratchbox\strutdp
\ht\scratchbox\strutht
\box\scratchbox
\egroup}
-\def\complexvl[#1]%
- {\dovlwdhtdp\plusone{#1}{#1}}
+\def\pack_rule_vl[#1]%
+ {\pack_rule_vl_indeed{#1}{#1}{#1}}
-\def\complexhl[#1]%
+\def\pack_rule_hl[#1]%
{\hbox
{\vrule
- \!!width #1\emwidth
- \!!height\linewidth
- \!!depth \zeropoint}}
+ \s!width #1\emwidth
+ \s!height\linewidth
+ \s!depth \zeropoint}}
+
+\unexpanded\def\vl{\dosingleempty\pack_rule_vl}
+\unexpanded\def\hl{\dosingleempty\pack_rule_hl}
-\definecomplexorsimple\vl \def\simplevl{\complexvl[\plusone]}
-\definecomplexorsimple\hl \def\simplehl{\complexhl[\plusone]}
+\let\dovlwdhtdp\pack_rule_vl_indeed % used elsewhere
%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 Drawing thin lines can of course easily be accomplished by the \TEX\
+%D primitives \type{\hrule} and \type{\vrule}. The next few macros however
+%D free us from some specifications.
%D
%D \startbuffer
%D some text
@@ -338,112 +217,158 @@
%D
%D which looks like: \thinrules[n=2]
-\newconstant\ruletype
+\installcorenamespace{thinrules}
+\installcorenamespace{thinrulealternatives}
+
+\installdirectcommandhandler \??thinrules {thinrules}
+
+\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=\linewidth]
+
+\letvalue{\??thinrulealternatives\v!a }\zerocount
+\letvalue{\??thinrulealternatives\v!b }\plusone
+\letvalue{\??thinrulealternatives\v!c }\plustwo
+\letvalue{\??thinrulealternatives\v!none}\zerocount
+
+\newconstant\c_pack_thinrules_type
\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}%
+ \edef\p_height {\directthinrulesparameter\c!height}%
+ \edef\p_depth {\directthinrulesparameter\c!depth}%
+ \edef\p_background{\directthinrulesparameter\c!background}%
+ \edef\p_frame {\directthinrulesparameter\c!frame}%
+ \linewidth\dimexpr\directthinrulesparameter\c!rulethickness/\plustwo\relax
\ifdim\linewidth=\zeropoint
- \ruletype\zerocount
+ \c_pack_thinrules_type\zerocount
+ \else\ifx\p_frame\v!on
+ \c_pack_thinrules_type\expandcheckedcsname\??thinrulealternatives{\directthinrulesparameter\c!alternative}\v!b\relax
\else
- \doifnot\@@dlframe\v!on{\ruletype\zerocount}%
+ \c_pack_thinrules_type\zerocount
+ \fi\fi
+ \ifnum\c_pack_thinrules_type=\plusone
+ \ifx\p_height\v!max
+ \scratchheight\strutht
+ \else
+ \setdimensionwithunit\scratchheight\p_height\strutht
+ \fi
+ \ifx\p_depth\v!max
+ \scratchdepth\strutdp
+ \else
+ \setdimensionwithunit\scratchdepth\p_depth\strutdp
+ \fi
+ \else
+ \scratchheight\strutht
+ \scratchdepth \strutdp
\fi
- \ifnum\ruletype=\plusone
- \doif\@@dlheight\v!max{\let\@@dlheight\!!plusone}%
- \doif\@@dldepth \v!max{\let\@@dldepth \!!plusone}%
+ \ifx\p_background\v!color
+ \startcolor[\directthinrulesparameter\c!backgroundcolor]%
+ \ifnum\c_pack_thinrules_type=\plustwo % prevent overshoot due to rounding
+ \leaders
+ \hrule
+ \s!height\dimexpr\scratchheight-\linewidth\relax
+ \s!depth \dimexpr\scratchdepth -\linewidth\relax
+ \hfill
+ \else
+ \leaders
+ \hrule
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \hfill
+ \fi
+ \stopcolor
+ \ifcase\c_pack_thinrules_type
+ % no rule
+ \or
+ \startcolor[\directthinrulesparameter\c!color]%
+ \hfillneg
+ \leaders
+ \hrule
+ \s!height\linewidth
+ \s!depth \linewidth
+ \hfill
+ \stopcolor
+ \or
+ \startcolor[\directthinrulesparameter\c!color]%
+ \hfillneg
+ \leaders
+ \hrule
+ \s!height\dimexpr-\scratchdepth+\linewidth\relax
+ \s!depth \scratchdepth
+ \hfill
+ \hfillneg
+ \leaders
+ \hrule
+ \s!height\scratchheight
+ \s!depth \dimexpr-\scratchheight+\linewidth\relax
+ \hfill
+ \stopcolor
+ \fi
\else
- \let\@@dlheight\!!plusone
- \let\@@dldepth\!!plusone
+ \ifcase\c_pack_thinrules_type
+ % no rule
+ \else
+ \startcolor[\directthinrulesparameter\c!color]%
+ \leaders
+ \hrule
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \hfill
+ \stopcolor
+ \fi
\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
+\unexpanded\def\hairline
{\endgraf
\thinrule
\endgraf}
-\def\dosetupthinrules[#1]%
- {\getparameters[\??dl][#1]}
+\unexpanded\def\thinrules
+ {\dosingleempty\pack_thinrules}
-\unexpanded\def\setupthinrules
- {\dosingleargument\dosetupthinrules}
-
-\def\dothinrules[#1]%
+\def\pack_thinrules[#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
+ \setupcurrentthinrules[#1]%
+ \assignvalue{\directthinrulesparameter\c!interlinespace}\m_pack_thinrules_interlinespace{1.0}{1.5}{2.0}%
+ \spacing\m_pack_thinrules_interlinespace
+ \edef\p_after {\directthinrulesparameter\c!after}%
+ \edef\p_inbetween{\directthinrulesparameter\c!inbetween}%
+ \directthinrulesparameter\c!before
+ \scratchcounter\directthinrulesparameter\c!n\relax
+ \dorecurse\scratchcounter
+ {\ifnum\recurselevel=\scratchcounter \penalty500 \else
+ \ifnum\recurselevel=\plustwo \penalty500 \fi\fi
+ \thinrule
+ \ifnum\recurselevel<\scratchcounter\relax
% test needed, else messed up whitespace
- \ifx\@@dlinbetween\empty
- \softbreak
+ \ifx\p_inbetween\empty
+ \softbreak % \ifhmode \hskip \parfillskip \break \fi
\else
\endgraf
\nowhitespace
- \@@dlinbetween
+ \p_inbetween
\fi
\fi}%
- \doifelsenothing\@@dlafter
- {\carryoverpar\egroup}
- {\@@dlafter\egroup}}
-
-\def\thinrules
- {\dosingleempty\dothinrules}
+ \ifx\p_after\empty
+ \carryoverpar\egroup
+ \else
+ \p_after\egroup
+ \fi{}}
%D A couple of examples are given below.
%D
@@ -464,11 +389,10 @@
%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 There are a couple of alternative ways to visualize rules using backgrounds. At
+%D first sight these may look strange, but they make sense in educational settings.
+%D The alternatives are more or less compatible with the more advanced \METAPOST\
+%D based implementation.
%D
%D \startbuffer[a]
%D \setupthinrules
@@ -507,22 +431,10 @@
%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 Putting rules before and after a paragraph is very space sensitive, but the
+%D next command handles that quite well. It comes in two disguises:
%D
%D \startbuffer
%D \textrule[top]{fragments}
@@ -562,132 +474,176 @@
%D \showsetup{starttextrule}
%D \showsetup{setuptextrules}
%D
-%D The implementation looks a bit complicated due to the
-%D optional arguments.
+%D The implementation looks a bit complicated due to the optional arguments.
-\unexpanded\def\setuptextrules
- {\dodoubleargument\getparameters[\??tl]}
+\installcorenamespace{textrules}
+\installcorenamespace{textrulealternatives}
-\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}
+\installdirectcommandhandler \??textrules {textrules}
-\definecomplexorsimple\textrule
+\setuptextrules
+ [\c!location=\v!left,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!inbetween=,
+ \c!width=2\emwidth,
+ \c!style=\v!bold,
+ \c!color=,
+ \c!rulecolor=,
+ \c!bodyfont=,
+ \c!depthcorrection=\v!on,
+ \c!rulethickness=\linewidth,
+ \c!distance=.5\emwidth]
-\def\simpletextrule
- {\dosinglegroupempty\dounknowntextrule}
+\unexpanded\def\textrule
+ {\dosingleempty\pack_textrule}
-\def\docomplextextrule#1%
+\def\pack_textrule
+ {\iffirstargument
+ \expandafter\pack_textrule_yes
+ \else
+ \expandafter\pack_textrule_nop
+ \fi}
+
+\def\pack_textrule_yes[#1]%
+ {\expandcheckedcsname\??textrulealternatives{#1}\v!bottom}
+
+\def\pack_textrule_nop[#1]%
+ {\dosinglegroupempty\pack_textrule_nop_indeed}
+
+\def\pack_textrule_nop_indeed
+ {\iffirstargument
+ \expandafter\pack_textrule_nop_indeed_yes
+ \else
+ \expandafter\pack_textrule_nop_indeed_nop
+ \fi}
+
+\def\pack_textrule_nop_indeed_yes
+ {\csname\??textrulealternatives\v!top\endcsname}
+
+\def\pack_textrule_nop_indeed_nop
+ {\csname\??textrulealternatives\v!bottom\endcsname\empty}
+
+%D\startbuffer
+%D\showstruts
+%D
+%D\setupwhitespace[none]
+%D
+%D\textrule[top]{test} xxxxx\smash{\strut} \textrule[bottom]{test}
+%D\textrule[top]{test} xxxxx\strut \textrule[bottom]{test}
+%D
+%D\setupwhitespace[big]
+%D
+%D\textrule[top]{test} xxxxx\smash{\strut} \textrule[bottom]{test}
+%D\textrule[top]{test} xxxxx\strut \textrule[bottom]{test}
+%D\stoptyping
+%D
+%D \typebuffer \start \getbuffer \stop
+
+\setvalue{\??textrulealternatives\v!top}#1%
+ {\page[\v!preference] % interferes
+ \directtextrulesparameter\c!before\relax
+ \blank[\v!samepage,\v!nowhite]%
+ \pack_textrule_with_text{#1}%
+ \blank[\v!samepage,\v!nowhite]%
+ \directtextrulesparameter\c!inbetween\relax
+ \endgraf}
+
+\setvalue{\??textrulealternatives\v!bottom}#1%
+ {\blank[\v!samepage,\v!nowhite]%
+ \pack_textrule_following{#1}%
+ \blank[\v!samepage,\v!nowhite]%
+ \directtextrulesparameter\c!after\relax
+ \page[\v!preference]}
+
+\setvalue{\??textrulealternatives\v!middle}#1%
+ {\blank[\v!samepage,\v!nowhite]%
+ \directtextrulesparameter\c!inbetween\relax
+ \pack_textrule_following{#1}%
+ \blank[\v!samepage,\v!nowhite]%
+ \directtextrulesparameter\c!inbetween\relax
+ \page[\v!preference]}
+
+\def\pack_textrule_with_text#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
+ \setbox\scratchbox\hbox to \availablehsize
+ {\scratchwidth \directtextrulesparameter\c!rulethickness\relax
+ \scratchheight\dimexpr .5\exheight+.5\scratchwidth\relax
+ \scratchdepth \dimexpr-.5\exheight+.5\scratchwidth\relax
\doifsomething{#1}
- {\doifelse\@@tllocation\v!inmargin
+ {\doifelse{\directtextrulesparameter\c!location}\v!inmargin
{\llap
- {\dousestyleparameter\@@tlstyle
- \dousecolorparameter\@@tlcolor
+ {\usetextrulesstyleandcolor\c!style\c!color
#1%
\hskip\leftmargindistance}}
- {\color[\@@tlrulecolor]
- {\vrule\!!height\dimen4\!!depth\dimen6\!!width\@@tlwidth}%
- \hbox spread 2\dimexpr\@@tldistance\relax
+ {\color[\directtextrulesparameter\c!rulecolor]
+ {\vrule\s!height\scratchheight\s!depth\scratchdepth\s!width\directtextrulesparameter\c!width}%
+ \hbox spread 2\dimexpr\directtextrulesparameter\c!distance\relax
{\hss
- \dousestyleparameter\@@tlstyle
- \dousecolorparameter\@@tlcolor
+ \usetextrulesstyleandcolor\c!style\c!color
\strut#1%
\hss}}}%
- \color[\@@tlrulecolor]
- {\leaders\hrule\!!height\dimen4\!!depth\dimen6\hfill}}%
+ \color[\directtextrulesparameter\c!rulecolor]
+ {\leaders\hrule\s!height\scratchheight\s!depth\scratchdepth\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
+\def\pack_textrule_correct_depth_yes
+ {\vskip\dimexpr
+ \strutdp +.5\exheight
+ \ifdim\prevdepth>\strutdp\else
+ \ifdim\prevdepth>\zeropoint
+ -\prevdepth
+ \fi
\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
+ \relax
+ \relax}
+
+\def\pack_textrule_correct_depth_nop
+ {\vskip\dimexpr
+ \strutdp +.5\exheight
+ \relax
+ \relax}
+
+\def\pack_textrule_following#1%
+ {\doifelsenothing{#1}
+ {\ifhmode
+ \endgraf
+ \fi
+ \doifelse{\directtextrulesparameter\c!depthcorrection}\v!on\pack_textrule_correct_depth_yes\pack_textrule_correct_depth_nop
\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
+ \dontleavehmode\vbox
+ {\color[\directtextrulesparameter\c!rulecolor]
+ {\hrule\s!depth\directtextrulesparameter\c!rulethickness\s!height\zeropoint\s!width\availablehsize}}}
+ {\pack_textrule_with_text{#1}}%
+ \ifvmode
+ \prevdepth\zeropoint
\fi}
%D The grouped commands also supports bodyfont switching:
\unexpanded\def\starttextrule#1%
{\bgroup
- \def\dounknowntextrule{\domiddletextrule}
- \dotoptextrule{#1}
+ \def\pack_textrule_nop_indeed{\csname\??textrulealternatives\v!middle\endcsname}%
+ \csname\??textrulealternatives\v!top\endcsname{#1}%
\bgroup
- \doifsomething\@@tlbodyfont{\switchtobodyfont[\@@tlbodyfont]}}
+ \doifsomething{\directtextrulesparameter\c!bodyfont}{\switchtobodyfont[\directtextrulesparameter\c!bodyfont]}}
\unexpanded\def\stoptextrule
{\par
\egroup
- \dobottomtextrule\empty
+ \csname\??textrulealternatives\v!bottom\endcsname\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 The next few commands do not really deserve a place in a core module, because
+%D they deal with specific typography. Nevertheless I decided to make them part of
+%D the core, because they permit us to make questionaires. Let's start with some
+%D examples.
%D
%D \fillinrules[n=2,width=fit]{first}
%D \fillinrules[n=2,width=broad]{first}
@@ -696,85 +652,112 @@
%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 The main command is \type{\fillinrules}. This command takes one and an optional
+%D second argument and sets a paragraph with empty visualized lines.
%D
%D \showsetup{fillinrules}
%D \showsetup{setupfillinrules}
-\unexpanded\def\setupfillinrules
- {\dodoubleargument\getparameters[\??il]}
-\definecomplexorsimpleempty\fillinrules
+\installcorenamespace{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}
+\installdirectcommandhandler \??fillinrules {fillinrules}
-\def\dodocomplexfillinrules[#1]#2#3#4%
+\setupfillinrules
+ [\c!width=\v!broad,
+ \c!distance=\emwidth,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!n=\plusone,
+ \c!interlinespace=\v!small,
+ \c!separator=,
+ \c!style=,
+ \c!color=]
+
+\unexpanded\def\fillinrules
+ {\dosingleempty\pack_fillinrules}
+
+\def\pack_fillinrules[#1]%
{\endgraf
- \@@ilbefore
\begingroup
- \setupfillinrules[#1]%
+ \setupcurrentfillinrules[#1]%
+ \let\pack_fillinrules_rule\thinrules
+ \dodoublegroupempty\pack_fillinrules_indeed}
+
+\def\pack_fillinrules_indeed#1#2%
+ {\directfillinrulesparameter\c!before
+ \setupcurrentthinrules
+ [\c!n=\directfillinrulesparameter\c!n,
+ \c!interlinespace=\directfillinrulesparameter\c!interlinespace,
+ \c!before=,
+ \c!after=]%
+ \scratchdistance\directfillinrulesparameter\c!distance\relax
+ \edef\m_fillinrules_one{#1}%
+ \edef\m_fillinrules_two{#2}%
\noindent
- \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
+ \ifx\m_fillinrules_one\empty \else
+ \edef\p_width{\directfillinrulesparameter\c!width}%
+ \ifx\p_width\v!fit
+ \scratchdistance\zeropoint
+ \hbox
+ \else\ifx\p_width\v!broad
+ \hbox
+ \else
+ \hbox to \directfillinrulesparameter\c!width
+ \fi\fi
+ \bgroup
+ \usefillinrulesstyleandcolor\c!style\c!color
+ \strut
+ \m_fillinrules_one
+ \hfill\directfillinrulesparameter\c!separator
+ \hskip\scratchdistance
+ \egroup
+ \fi
\setupwhitespace[\v!big]%
\ignorespaces
- #4%
- \doifsomething{#3}
- {\kern\@@ildistance
- \dousestyleparameter\@@ilstyle
- \dousecolorparameter\@@ilcolor
- #3\strut}%
- \endgroup
+ \pack_fillinrules_rule
+ \ifx\m_fillinrules_two\empty \else
+ \kern\scratchdistance
+ \usefillinrulesstyleandcolor\c!style\c!color
+ \m_fillinrules_two
+ \strut
+ \fi
\endgraf
- \@@ilafter}
+ \directfillinrulesparameter\c!after
+ \endgroup}
%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 To provide compatible layouts when texts and lines are mixed, one can typeset
+%D a paragraph by using the command \type {\fillintext}.
%D
%D \showsetup{fillintext}
-\definecomplexorsimpleempty\fillintext
+\unexpanded\def\fillintext
+ {\dosingleempty\pack_fillintext}
+
+\def\pack_fillintext[#1]% ugly
+ {\endgraf
+ \begingroup
+ \setupcurrentfillinrules[#1]%
+ \dodoublegroupempty\pack_fillintext_indeed}
-\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}
+\def\pack_fillintext_indeed#1#2%
+ {\def\pack_fillinrules_rule{\unhbox\nextbox\unskip}%
+ \dowithnextbox{\pack_fillinrules_indeed{#1}{\hfill#2}}%
+ \hbox\bgroup\let\par\egroup\ignorespaces}
%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 Another member of the family takes care of putting a (often small) rule after
+%D a piece of text, like
%D
%D \startbuffer
-%D \fillinline \input reich \par
+%D
+%D \stopbuffer\fillinline \input reich \par
%D \fillinline[margin=0cm] \input reich \par
-%D \stopbuffer
%D
%D \startexample
%D \getbuffer
@@ -789,82 +772,71 @@
%D \showsetup{fillinline}
%D \showsetup{setupfillinlines}
-\unexpanded\def\setupfillinlines
- {\dodoubleargument\getparameters[\??iv]}
-
-\definecomplexorsimpleempty\fillinline
+\installcorenamespace{fillinlines}
-\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]
+\installdirectcommandhandler \??fillinlines {fillinlines}
-\setupthinrules
- [\c!interlinespace=\v!small,
- \c!n=3,
- \c!before=,
- \c!inbetween={\blank[\v!white]},
- \c!after=,
+\setupfillinlines
+ [\c!width=8\emwidth, % was 3cm
+ \c!margin=\directfillinlinesparameter\c!width,
+ \c!rulethickness=\linewidth,
\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!distance=\emwidth,
\c!before=\blank,
- \c!after=\blank,
- \c!inbetween=,
- \c!width=2em,
- \c!style=\v!bold,
- \c!color=,
- \c!rulecolor=,
- \c!bodyfont=,
- \c!distance=.5em]
+ \c!after=\blank]
-\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=]
+\unexpanded\def\fillinline
+ {\dosingleempty\pack_fillinline}
+
+\ifdefined\endpar % experiment with \endpar
+
+ \def\pack_fillinline[#1]%
+ {% \endpar % no, as it interferes with \definedescription cum suis
+ \begingroup
+ \setupcurrentfillinlines[#1]%
+ \directfillinlinesparameter\c!before
+ \begingroup
+ \advance\rightskip \directfillinlinesparameter\c!margin\relax
+ \parfillskip\zeropoint
+ \pushmacro\endpar
+ \def\endpar
+ {\popmacro\endpar
+ \ifhmode\unskip\hfill\fi
+ \scratchwidth\dimexpr\directfillinlinesparameter\c!width-\directfillinlinesparameter\c!distance\relax
+ \ifdim\scratchwidth>\directfillinlinesparameter\c!margin\else\expandafter\rlap\fi
+ {\kern\directfillinlinesparameter\c!distance
+ \scratchheight\dimexpr\directfillinlinesparameter\c!rulethickness/\plustwo\relax
+ \color[\directfillinlinesparameter\c!color]{\vrule\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchheight}}%
+ \endpar
+ \endgroup
+ \endpar
+ \directfillinlinesparameter\c!after
+ \endgroup}} % carryover ?
+
+\else
+
+ \def\pack_fillinline[#1]%
+ {%\endgraf % no, as it interferes with \definedescription cum suis
+ \begingroup
+ \setupcurrentfillinlines[#1]%
+ \directfillinlinesparameter\c!before
+ \begingroup
+ \advance\rightskip \directfillinlinesparameter\c!margin\relax
+ \parfillskip\zeropoint
+ \def\par
+ {\let\par\endgraf
+ \ifhmode\unskip\hfill\fi
+ \scratchwidth\dimexpr\directfillinlinesparameter\c!width-\directfillinlinesparameter\c!distance\relax
+ \ifdim\scratchwidth>\directfillinlinesparameter\c!margin\else\expandafter\rlap\fi
+ {\kern\directfillinlinesparameter\c!distance
+ \scratchheight\dimexpr\directfillinlinesparameter\c!rulethickness/\plustwo\relax
+ \color[\directfillinlinesparameter\c!color]{\vrule\s!width\scratchwidth\s!height\scratchheight\s!depth\scratchheight}}%
+ \endgraf
+ \endgroup
+ \endgraf
+ \directfillinlinesparameter\c!after
+ \endgroup}} % carryover ?
-\setupfillinlines
- [\c!width=3cm,
- \c!margin=\@@ivwidth,
- \c!distance=1em,
- \c!before=\blank,
- \c!after=\blank]
+\fi
\protect \endinput
diff --git a/tex/context/base/pack-obj.lua b/tex/context/base/pack-obj.lua
index c580aaa62..1e4e0f59e 100644
--- a/tex/context/base/pack-obj.lua
+++ b/tex/context/base/pack-obj.lua
@@ -11,6 +11,8 @@ if not modules then modules = { } end modules ['pack-obj'] = {
reusable components.</p>
--ldx]]--
+local commands, context = commands, context
+
local texcount = tex.count
local allocate = utilities.storage.allocate
@@ -46,15 +48,30 @@ end
function jobobjects.number(tag,default)
local o = collected[tag] or tobesaved[tag]
- context((o and o[1]) or default)
+ return o and o[1] or default
end
function jobobjects.page(tag,default)
local o = collected[tag] or tobesaved[tag]
- context((o and o[2]) or default)
+ return o and o[2] or default
+end
+
+-- interface
+
+commands.saveobject = jobobjects.save
+commands.setobject = jobobjects.set
+
+function commands.objectnumber(tag,default)
+ local o = collected[tag] or tobesaved[tag]
+ context(o and o[1] or default)
+end
+
+function commands.objectpage(tag,default)
+ local o = collected[tag] or tobesaved[tag]
+ context(o and o[2] or default)
end
-function jobobjects.doifelse(tag)
- commands.testcase(collected[tag] or tobesaved[tag])
+function commands.doifobjectreferencefoundelse(tag)
+ commands.doifelse(collected[tag] or tobesaved[tag])
end
diff --git a/tex/context/base/pack-obj.mkiv b/tex/context/base/pack-obj.mkiv
index 6c9848a01..356a0b7eb 100644
--- a/tex/context/base/pack-obj.mkiv
+++ b/tex/context/base/pack-obj.mkiv
@@ -105,29 +105,27 @@
%
% \everyobject{\the\pdfbackendeveryxform}
%
-% \let\doresetobjects\relax
-%
-% \def\setobject #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\the\everyobject\dowithnextbox{\dosetobject{#1}{#2}}}
-% \def\settightobject#1#2{\begingroup\objectoff\zeropoint \inobjecttrue\the\everyobject\dowithnextbox{\dosetobject{#1}{#2}}}
+% \unexpanded\def\setobject #1#2{\begingroup\objectoff\objectoffset\inobjecttrue\the\everyobject\dowithnextbox{\pack_objects_set{#1}{#2}}}
+% \unexpanded\def\settightobject#1#2{\begingroup\objectoff\zeropoint \inobjecttrue\the\everyobject\dowithnextbox{\pack_objects_set{#1}{#2}}}
%
% \let\objectsetvbox\vbox %\def\objectsetvbox{\ruledvbox}
% \let\objectgetvbox\vbox %\def\objectgetvbox{\ruledvbox}
% \let\objectsethbox\hbox %\def\objectsethbox{\ruledhbox}
% \let\objectgethbox\hbox %\def\objectgethbox{\ruledhbox}
%
-% \def\dosetobject#1#2%
+% \unexpanded\def\pack_objects_set#1#2%
% {\objectwd\wd\nextbox
% \objectht\ht\nextbox
% \objectdp\dp\nextbox
% \ifdim\objectoff=\zeropoint\relax
% \setbox\objectbox\box\nextbox
% \else
-% \setbox\objectbox\objectsetvbox spread 2\objectoff{\vss\objectsethbox spread 2\objectoff{\hss\flushnextbox\hss}\vss}%
+% \setbox\objectbox\objectsetvbox spread 2\objectoff{\vss\objectsethbox spread 2\objectoff{\hss\box\nextbox\hss}\vss}%
% \fi
% \ctxlua{objects.register("#1::#2")}%
% \endgroup}
%
-% \def\getobject#1#2%
+% \unexpanded\def\getobject#1#2%
% {\begingroup
% \ctxlua{objects.restore("#1::#2")}%
% \ifdim\objectoff=\zeropoint\relax \else
@@ -140,7 +138,7 @@
% \box\objectbox
% \endgroup}
%
-% \def\getpageobject#1#2%
+% \unexpanded\def\getpageobject#1#2%
% {\begingroup
% \ctxlua{objects.restore("#1::#2")}%
% \ifdim\objectoff=\zeropoint\relax
@@ -155,25 +153,25 @@
% \box\objectbox
% \endgroup}
%
-% \def\setobjectdirectly #1#2{\ctxlua{objects.register("#1::#2")}}
-% \def\getobjectdirectly #1#2{\ctxlua{objects.restore ("#1::#2")}}
-% \def\getobjectdimensions #1#2{\ctxlua{objects.restore ("#1::#2")}}
-% \def\doifobjectfoundelse #1#2{\ctxlua{objects.doifelse("#1::#2")}}
-% \def\doifobjectreferencefoundelse#1#2{\ctxlua{objects.doifelse("#1::#2")}}
+% \unexpanded\def\setobjectdirectly #1#2{\ctxlua{objects.register("#1::#2")}}
+% \unexpanded\def\getobjectdirectly #1#2{\ctxlua{objects.restore ("#1::#2")}}
+% \unexpanded\def\getobjectdimensions #1#2{\ctxlua{objects.restore ("#1::#2")}}
+% \unexpanded\def\doifobjectfoundelse #1#2{\ctxlua{objects.doifelse("#1::#2")}}
+% \unexpanded\def\doifobjectreferencefoundelse#1#2{\ctxlua{objects.doifelse("#1::#2")}}
%
% \let\objectreferenced\relax
% \let\driverreferenced\relax
%
-% \def\doregisterobjectreference{\writestatus{objects}{obsolete: register object reference}\gobblethreearguments}
-% \def\dooverloadobjectreference{\writestatus{objects}{obsolete: overload object reference}\gobblethreearguments}
-% \def\dosetobjectreference {\writestatus{objects}{obsolete: set object reference}\gobblethreearguments}
-% \def\dosetdriverreference {\writestatus{objects}{obsolete: set driver reference}\gobblethreearguments}
+% \unexpanded\def\pack_objects_register_reference{\writestatus{objects}{obsolete: register object reference}\gobblethreearguments}
+% \unexpanded\def\pack_objects_overload_reference{\writestatus{objects}{obsolete: overload object reference}\gobblethreearguments}
+% \unexpanded\def\dosetobjectreference {\writestatus{objects}{obsolete: set object reference}\gobblethreearguments}
+% \unexpanded\def\dosetdriverreference {\writestatus{objects}{obsolete: set driver reference}\gobblethreearguments}
%
% \def\defaultobjectreference{0}
% \def\defaultobjectpage {\realfolio}
%
-% \def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{objects.reference("#1::#2)}}}
-% \def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{objects.page("#1::#2))}}}
+% \unexpanded\def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{objects.reference("#1::#2)}}}
+% \unexpanded\def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{objects.page("#1::#2))}}}
%
% \protect
%
@@ -219,26 +217,27 @@
%D housekeeping to the driver. The current approach permits
%D us to keep the box characteristic too.
-\newif\ifinobject
+\installcorenamespace {objects}
+
+\newif\ifinobject % public (might become a conditional)
-\def\objectplaceholder{NOT YET FLUSHED}%
+\def\objectplaceholder{NOT YET FLUSHED}
-\def\presetobject#1#2% \global added
- {\ifcsname\??ob:#1::#2\endcsname\else
- \global\@EA\let\csname\??ob:#1::#2\endcsname\objectplaceholder
+\unexpanded\def\presetobject#1#2% \global added
+ {\ifcsname\??objects#1::#2\endcsname\else
+ \global\expandafter\let\csname\??objects#1::#2\endcsname\objectplaceholder
\fi}
-\def\dosetobject#1#2#3% \initializepaper this will move to \everyshipout
- {% \initializepaper
- \ifcsname\??ob:#2::#3\endcsname
+\unexpanded\def\pack_objects_set#1#2#3%
+ {\ifcsname\??objects#2::#3\endcsname
\expandafter\gobblefivearguments
\else % tzt, overload internal referenced objects to save entries
- \expandafter\dodosetobject
+ \expandafter\pack_objects_set_indeed
\fi
{#1}{#2}{#3}}
-\def\resetobject#1#2%
- {\letbeundefined{\??ob:#1::#2}}
+\unexpanded\def\resetobject#1#2%
+ {\letbeundefined{\??objects#1::#2}}
%D \macros
%D {finalizeobjectbox}
@@ -246,7 +245,7 @@
%D This one provides a hook for last minute object box processing
%D we need this in \MKIV.
-\ifx\finalizeobjectbox\undefined
+\ifdefined\finalizeobjectbox \else
\let\finalizeobjectbox\gobbleoneargument
\fi
@@ -257,47 +256,54 @@
\def\objectoffset{1cm}
-\def\dodosetobject#1#2#3%
+\unexpanded\def\pack_objects_set_indeed#1#2#3%
{\bgroup
- \globalpushmacro\crossreferenceobject \objectreferenced
+ \globalpushmacro\crossreferenceobject
+ \objectreferenced
\inobjecttrue
\dowithnextbox
{\globalpopmacro\crossreferenceobject
- \dododosetobject{#1}{#2}{#3}\egroup}}
+ \pack_objects_set_indeed_indeed{#1}{#2}{#3}%
+ \egroup}}
% in luatex version < 66 we had a 1bp compensation (hardcoded in luatex)
-\def\dododosetobject#1#2#3%
+\let\pack_objects_handle\relax
+
+\unexpanded\def\pack_objects_set_indeed_indeed#1#2#3%
{\begingroup
\scratchdimen\objectoffset
- \@EA\xdef\csname\??ob:#2::#3\endcsname
- {\noexpand\dohandleobject{#2}{#3}%
+ \expandafter\xdef\csname\??objects#2::#3\endcsname
+ {\pack_objects_handle
+ {#2}%
+ {#3}%
{\ifhbox\nextbox\hbox\else\vbox\fi}%
- {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}%
+ {\number\wd\nextbox}%
+ {\number\ht\nextbox}%
+ {\number\dp\nextbox}%
{\number\scratchdimen}}%
\expanded % freeze the dimensions since \dostartobject may use \nextbox
- {\dostartobject{#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}%
+ {\dostartobject{#2}{#3}{\the\wd\nextbox}{\the\ht\nextbox}{\the\dp\nextbox}}%
\ifcase#1\relax\else \ifdim\objectoffset>\zeropoint
- \setbox\nextbox\vbox spread 2\scratchdimen
+ \setbox\nextbox\vbox \s!spread 2\scratchdimen
{\forgetall \offinterlineskip
- \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}%
+ \vss\hbox \s!spread 2\scratchdimen{\hss\box\nextbox\hss}\vss}%
\fi \fi
- \flushnextbox
+ \box\nextbox
\dostopobject
\endgroup}
-\def\getobject#1#2%
- {\ifcsname\??ob:#1::#2\endcsname
+\unexpanded\def\getobject#1#2%
+ {\ifcsname\??objects#1::#2\endcsname
\begingroup
- \let\dohandleobject\dogetobject
- \csname\??ob:#1::#2\expandafter\endcsname
+ \let\pack_objects_handle\pack_objects_get
+ \csname\??objects#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
+\unexpanded\def\pack_objects_get#1#2#3#4#5#6#7% don't change this, should work for dvi & pdf
+ {\forgetall
% todo: if no attr then faster
\setbox\scratchbox\vbox attr \viewerlayerattribute \attribute\viewerlayerattribute
{\doinsertobject{#1}{#2}}%
@@ -323,18 +329,18 @@
%D The results are reported in \type {\objectwidth}, \type
%D {\objectheight} and \type {\objectdepth}.
-\def\dogetobjectdimensions#1#2#3#4#5#6#7%
+\unexpanded\def\pack_objects_get_dimensions#1#2#3#4#5#6#7%
{\def\objectwidth {#4\s!sp}%
\def\objectheight{#5\s!sp}%
\def\objectdepth {#6\s!sp}%
\def\objectmargin{#7\s!sp}}
-\def\getobjectdimensions#1#2%
- {\let\dohandleobject\dogetobjectdimensions
+\unexpanded\def\getobjectdimensions#1#2%
+ {\let\pack_objects_handle\pack_objects_get_dimensions
\let\objectwidth \!!zeropoint
\let\objectheight\!!zeropoint
\let\objectdepth \!!zeropoint
- \csname\??ob:#1::#2\endcsname}
+ \csname\??objects#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
@@ -352,35 +358,35 @@
%D These commands are to be called by the \type{\startobject},
%D \type{\stopobject} and \type{\insertobject} specials.
-\def\objectreferenced{\global\chardef\crossreferenceobject\plusone}
-\def\driverreferenced{\global\chardef\crossreferenceobject\zerocount}
+\unexpanded\def\objectreferenced{\global\chardef\crossreferenceobject\plusone}
+\unexpanded\def\driverreferenced{\global\chardef\crossreferenceobject\zerocount}
\objectreferenced
% no undefined test ! ! ! ! (pdftex fails on undefined objects)
-\def\doregisterobjectreference#1#2#3{\normalexpanded{\noexpand\ctxlatelua{job.objects.save("#1::#2",#3,\noexpand\the\realpageno)}}}
-\def\dooverloadobjectreference#1#2#3{\ctxlua{job.objects.set("#1::#2",#3,\the\realpageno)}}
+\unexpanded\def\pack_objects_register_reference#1#2#3{\normalexpanded{\noexpand\ctxlatecommand{saveobject("#1::#2",#3,\noexpand\the\realpageno)}}}
+\unexpanded\def\pack_objects_overload_reference#1#2#3{\ctxcommand{setobject("#1::#2",#3,\the\realpageno)}}
-\def\dosetobjectreference
+\unexpanded\def\dosetobjectreference
{\ifcase\crossreferenceobject
\objectreferenced
- \expandafter\dooverloadobjectreference
+ \expandafter\pack_objects_overload_reference
\else
- \expandafter\doregisterobjectreference
+ \expandafter\pack_objects_register_reference
\fi}
-\def\dosetdriverreference
+\unexpanded\def\dosetdriverreference
{\driverreferenced\dosetobjectreference}
\def\defaultobjectreference#1#2{0} % driver dependent
\def\defaultobjectpage #1#2{\realfolio}
-\def\dogetobjectreference #1#2#3{\xdef#3{\ctxlua{job.objects.number("#1::#2","\defaultobjectreference{#1}{#2}")}}}
-\def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxlua{job.objects.page("#1::#2","\defaultobjectpage{#1}{#2}")}}}
+\unexpanded\def\dogetobjectreference #1#2#3{\xdef#3{\ctxcommand{objectnumber("#1::#2","\defaultobjectreference{#1}{#2}")}}}
+\unexpanded\def\dogetobjectreferencepage#1#2#3{\xdef#3{\ctxcommand{objectpage("#1::#2","\defaultobjectpage{#1}{#2}")}}}
-\def\setobject {\driverreferenced\dosetobject1}
-\def\settightobject{\driverreferenced\dosetobject0}
+\unexpanded\def\setobject {\driverreferenced\pack_objects_set1}
+\unexpanded\def\settightobject{\driverreferenced\pack_objects_set0}
%D \macros
%D {doifobjectfoundelse,doifobjectreferencefoundelse}
@@ -393,13 +399,14 @@
%D \doifobjectreferencefoundelse{class}{object}{do then}{do else}
%D \stoptyping
-\def\doifobjectfoundelse#1#2%
- {\ifcsname\??ob:#1::#2\endcsname
+\unexpanded\def\doifobjectfoundelse#1#2%
+ {\ifcsname\??objects#1::#2\endcsname
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\def\doifobjectreferencefoundelse#1#2{\ctxlua{job.objects.doifelse("#1::#2")}}
+\unexpanded\def\doifobjectreferencefoundelse#1#2%
+ {\ctxcommand{doifobjectreferencefoundelse("#1::#2")}}
\protect \endinput
diff --git a/tex/context/base/pack-pos.mkiv b/tex/context/base/pack-pos.mkiv
index fab73bc4a..ff8244f0a 100644
--- a/tex/context/base/pack-pos.mkiv
+++ b/tex/context/base/pack-pos.mkiv
@@ -23,114 +23,141 @@
% \position[ystep=relative](3,-1){test}
% \position(10,10){test}
% \stoppositioning}
+%
+% watch out: rather global
-\newdimen\positioningxposition \newdimen\positioningyposition
-\newdimen\positioningxdimension \newdimen\positioningydimension
-\newdimen\positioningxoffset \newdimen\positioningyoffset
+\installcorenamespace {positioning}
-\newbox\positioningbox
+\installcommandhandler \??positioning {positioning} \??positioning
-\unexpanded\def\startpositioning
- {\dosingleempty\dostartpositioning}
+\setuppositioning
+ [\c!state=\v!start,
+ \c!unit=\s!cm,
+ \c!factor=\plusone,
+ \c!scale =\plusone,
+ \c!xfactor=\positioningparameter\c!factor,
+ \c!yfactor=\positioningparameter\c!factor,
+ \c!xscale=\positioningparameter\c!scale,
+ \c!yscale=\positioningparameter\c!scale,
+ \c!xstep=\v!absolute,
+ \c!ystep=\v!absolute,
+ \c!xoffset=\zeropoint,
+ \c!yoffset=\zeropoint]
+
+\newdimen\d_pack_positioning_x_position
+\newdimen\d_pack_positioning_y_position
+\newdimen\d_pack_positioning_x_dimension
+\newdimen\d_pack_positioning_y_dimension
+\newdimen\d_pack_positioning_x_offset
+\newdimen\d_pack_positioning_y_offset
-\def\dostartpositioning[#1]%
+\newbox\b_pack_positioning
+
+\unexpanded\def\startpositioning
{\bgroup
- \getparameters[\??ps][#1]%
- \positioningxposition \zeropoint \positioningyposition \zeropoint
- \positioningxdimension\zeropoint \positioningydimension\zeropoint
- \positioningxoffset \zeropoint \positioningyoffset \zeropoint
- \hfuzz \paperwidth \vfuzz \paperheight
- \setbox\positioningbox\hbox\bgroup
+ \dodoubleempty\pack_positioning_start}
+
+\def\pack_positioning_start[#1][#2]%
+ {\ifsecondargument
+ \edef\currentpositioning{#1}%
+ \setupcurrentpositioning[#2]%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\let\currentpositioning\empty
+ \setupcurrentpositioning[#1]}%
+ {\edef\currentpositioning{#1}}%
+ \else
+ \let\currentpositioning\empty
+ \fi\fi
+ \d_pack_positioning_x_position \zeropoint
+ \d_pack_positioning_y_position \zeropoint
+ \d_pack_positioning_x_dimension\zeropoint
+ \d_pack_positioning_y_dimension\zeropoint
+ \d_pack_positioning_x_offset \zeropoint
+ \d_pack_positioning_y_offset \zeropoint
+ \hfuzz\paperwidth
+ \vfuzz\paperheight
+ \setbox\b_pack_positioning\hbox\bgroup
\ignorespaces}
\unexpanded\def\stoppositioning
{\removeunwantedspaces
- \doifnot\@@psoffset\v!yes
- {\global\positioningxoffset\zeropoint
- \global\positioningyoffset\zeropoint}%
- \global\advance\positioningxdimension \positioningxoffset
- \global\advance\positioningydimension \positioningyoffset
+ \doifnot{\positioningparameter\c!offset}\v!yes
+ {\global\d_pack_positioning_x_offset\zeropoint
+ \global\d_pack_positioning_y_offset\zeropoint}%
+ \global\advance\d_pack_positioning_x_dimension\d_pack_positioning_x_offset
+ \global\advance\d_pack_positioning_y_dimension\d_pack_positioning_y_offset
\egroup
- \vbox to \positioningydimension
- {\vskip\positioningyoffset
- \hbox to \positioningxdimension
- {\hskip\positioningxoffset
- \box\positioningbox
+ \vbox to \d_pack_positioning_y_dimension
+ {\vskip\d_pack_positioning_y_offset
+ \hbox to \d_pack_positioning_x_dimension
+ {\hskip\d_pack_positioning_x_offset
+ \box\b_pack_positioning
\hfill}
\vfill}%
\egroup}
-\def\resetpositioning
- {\let\@@psstate \v!start
- \let\@@psunit \s!cm
- \let\@@psfactor \plusone
- \let\@@psscale \plusone
- \def\@@psxfactor{\@@psfactor}%
- \def\@@psyfactor{\@@psfactor}%
- \def\@@psxscale {\@@psscale}%
- \def\@@psyscale {\@@psscale}%
- \let\@@psxstep \v!absolute
- \let\@@psystep \v!absolute
- \let\@@psxoffset \zeropoint
- \let\@@psyoffset \zeropoint}
-
-\resetpositioning
-
-\unexpanded\def\setuppositioning
- {\resetpositioning
- \dodoubleargument\getparameters[\??ps]}
-
-\def\calculateposition#1#2#3#4#5#6#7#8#9%
- {\setdimensionwithunit\scratchdimen{#1}\@@psunit
- \scratchdimen#8\scratchdimen
- \scratchdimen#9\scratchdimen
- \advance\scratchdimen #4\relax
+\unexpanded\def\pack_positioning_calculate#1#2#3#4#5#6#7#8#9%
+ {\setdimensionwithunit\scratchdimen{#1}{\positioningparameter\c!unit}%
+ \scratchdimen\positioningparameter#8\scratchdimen
+ \scratchdimen\positioningparameter#9\scratchdimen
+ \advance\scratchdimen\positioningparameter#4\relax
% == \scratchdimen\dimexpr#8\dimexpr#9\scratchdimen\relax+#4\relax
- \doif{#2}\v!relative
+ \doif{\positioningparameter#2}\v!relative
{\advance\scratchdimen#3%
- \let#4\zeropoint}%
+ \letpositioningparameter#4\zeropoint}%
#3\scratchdimen
- \doifnot\@@psstate\v!overlay
- {\scratchdimen\dimexpr#5+#3\relax
+ \doifnot{\positioningparameter\c!state}\v!overlay
+ {\scratchdimen\dimexpr#5\nextbox+#3\relax
\ifdim #3<-#7\relax \global#7-#3\relax \fi
\ifdim\scratchdimen> #6\relax \global#6\scratchdimen\fi}}
-\def\position
- {\dosingleempty\doposition}
-
-\def\doposition[#1]#2(#3,#4)%
- {\removeunwantedspaces
- \dowithnextbox{\dodoposition{#1}{#2}{#3}{#4}}\hbox}
-
-\def\dodoposition#1#2#3#4%
+\unexpanded\def\position
{\bgroup
- \dontcomplain
- \getparameters[\??ps][#1]%
- \calculateposition{#3}\@@psxstep\positioningxposition\@@psxoffset\nextboxwd \positioningxdimension\positioningxoffset\@@psxscale\@@psxfactor
- \calculateposition{#4}\@@psystep\positioningyposition\@@psyoffset\nextboxhtdp\positioningydimension\positioningyoffset\@@psyscale\@@psyfactor
+ \dosingleempty\pack_positioning_position}
+
+\def\pack_positioning_position[#1]#2(#3,#4)%
+ {\iffirstargument
+ \setupcurrentpositioning[#1]%
+ \fi
+ \removeunwantedspaces
+ \dowithnextbox{\pack_positioning_position_indeed{#3}{#4}}\hbox}
+
+\def\pack_positioning_position_indeed#1#2%
+ {\dontcomplain
+ \pack_positioning_calculate
+ {#1}%
+ \c!xstep
+ \d_pack_positioning_x_position
+ \c!xoffset
+ \wd
+ \d_pack_positioning_x_dimension
+ \d_pack_positioning_x_offset
+ \c!xscale
+ \c!xfactor
+ \pack_positioning_calculate
+ {#2}%
+ \c!ystep
+ \d_pack_positioning_y_position
+ \c!yoffset
+ \htdp
+ \d_pack_positioning_y_dimension
+ \d_pack_positioning_y_offset
+ \c!yscale
+ \c!yfactor
\vbox to \zeropoint
- {\vskip\positioningyposition
+ {\vskip\d_pack_positioning_y_position
\hbox to \zeropoint
- {\hskip\positioningxposition
- \flushnextbox
+ {\hskip\d_pack_positioning_x_position
+ \box\nextbox
\hss}
\vss}%
\normalexpanded
{\egroup
- \positioningxposition\the\positioningxposition
- \positioningyposition\the\positioningyposition
- \def\noexpand\@@psxoffset{\the\dimexpr\@@psxoffset}%
- \def\noexpand\@@psyoffset{\the\dimexpr\@@psyoffset}}%
+ \d_pack_positioning_x_position\the\d_pack_positioning_x_position
+ \d_pack_positioning_y_position\the\d_pack_positioning_y_position
+ \setexpandedpositioningparameter\c!xoffset{\the\dimexpr\positioningparameter\c!xoffset}%
+ \setexpandedpositioningparameter\c!yoffset{\the\dimexpr\positioningparameter\c!yoffset}}%
\ignorespaces}
-\setuppositioning
- [\c!unit=\s!cm,
- \c!factor=\plusone,
- \c!scale=\plusone,
- \c!xstep=\v!absolute,
- \c!ystep=\v!absolute,
- \c!offset=\v!yes,
- \c!xoffset=\zeropoint,
- \c!yoffset=\zeropoint]
-
\protect \endinput
diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv
index 480997919..9eb44b747 100644
--- a/tex/context/base/pack-rul.mkiv
+++ b/tex/context/base/pack-rul.mkiv
@@ -13,31 +13,27 @@
\writestatus{loading}{ConTeXt Packaging Macros / Ruled Content}
-%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.
-
-% eventually this will use the commandhandler code (same trick as
-% with itemize)
+%D The code here is expanded lots of time as framed is used in many places. This is
+%D why the code here is (and gets) optimized as much as possible. Also, by avoiding
+%D packaging and expansion we also keep tracing reasonable. For instance, multiple
+%D stacked backgrounds can slow down a run if not optimized this way.
\registerctxluafile{pack-rul}{1.001}
\unprotect
+\definesystemvariable {ol} % OmLijnd -> check scrn-fld too
+
%D \macros
%D {linewidth, setuplinewidth}
%D
-%D This module deals with rules (lines) in several ways. First
-%D we introduce two macros that can be used to set some common
-%D characteristics.
+%D This module deals with rules (lines) in several ways. First we introduce two
+%D macros that can be used to set some common characteristics.
%D
%D \showsetup{setuplinewidth}
%D
-%D The linewidth is available in \type{\linewidth}. The
-%D preset value of .4pt equals the default hard coded \TEX\
-%D rule width.
+%D The linewidth is available in \type{\linewidth}. The preset value of .4pt equals
+%D the default hard coded \TEX\ rule width.
\newdimen\linewidth
@@ -54,8 +50,16 @@
%D
%D \showsetup{setupscreens}
-\unexpanded\def\setupscreens
- {\dodoubleargument\getparameters[\??rs]}
+\installcorenamespace{screens}
+
+\installsetuponlycommandhandler \??screens {screens}
+
+\appendtoks
+ \edef\defaultbackgroundscreen{\directscreensparameter\c!screen}
+\to \everysetupscreens
+
+\setupscreens
+ [\c!screen=.90] % was .95 but that's hardly visible
%D The parameter handler:
@@ -65,41 +69,26 @@
\installcorenamespace{framedleft}
\installcorenamespace{framedright}
-\let\currentframed\s!unknown % brrr must have a value
-
-% \def\framedparameter #1{\csname\doframedparameter\currentframed{#1}\endcsname}
-% \def\framedparameterhash#1{\doframedparameterhash \currentframed#1}
-
-\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}
+\installcorenamespace{regularframed}
+\installcorenamespace{simplifiedframed}
-\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}
+\installcommandhandler \??framed {framed} \??framed
-\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}
+\let\pack_framed_framedparameter \framedparameter
+\let\pack_framed_framedparameterhash\framedparameterhash
+\let\pack_framed_setupcurrentframed \setupcurrentframed
-\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\pack_framed_initialize
+ {\let\framedparameter \pack_framed_framedparameter
+ \let\framedparameterhash\pack_framed_framedparameterhash
+ \let\setupcurrentframed \pack_framed_setupcurrentframed
+ \inframedtrue}
-\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}
+%D A helper:
\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}
+%D Inheritance:
\def\installinheritedframed#1%
{\normalexpanded{\doinstallinheritedframed
@@ -109,19 +98,21 @@
\expandafter\noexpand\csname do#1parameter\endcsname
\expandafter\noexpand\csname do#1parentparameter\endcsname
\expandafter\noexpand\csname do#1rootparameter\endcsname
+ \expandafter\noexpand\csname setupcurrent#1\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%
+\unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9%
+ {\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}%
+ \def#6##1{\ifcsname#9:##1\endcsname#9:##1\else\s!empty\fi}% root
+ \unexpanded\def#8%
{\bgroup
\bgroup
\inframedtrue
- \let\currentframed #1% not used (more for tracing)
+ \let\currentframed #1%
\let\framedparameter #2%
\let\framedparameterhash#3%
+ \let\setupcurrentframed #7%
\pack_framed_process_indeed}}
\unexpanded\def\installframedcommandhandler#1#2#3%
@@ -138,12 +129,11 @@
% for regular framed
-\getparameters
- [\??framed]
+\setupframed
[\c!width=\v!fit,
\c!height=\v!broad,
%\c!lines=,
- \c!offset=0.25ex, % \defaultframeoffset
+ \c!offset=.25ex, % \defaultframeoffset
\c!empty=\v!no,
\c!frame=\v!on,
%\c!topframe=,
@@ -158,11 +148,12 @@
%\c!foregroundstyle=,
%\c!background=,
%\c!backgroundscreen=,
+ \c!backgroundscreen=\defaultbackgroundscreen,
%\c!backgroundcolor=,
\c!backgroundoffset=\zeropoint,
%\c!framecolor=,
\c!frameoffset=\zeropoint,
- \c!backgroundcorner=\framedparameter\c!corner,
+ \c!backgroundcorner=\framedparameter\c!corner, % use \p_ here
\c!backgroundradius=\framedparameter\c!radius,
\c!backgrounddepth=\framedparameter\c!depth,
\c!framecorner=\framedparameter\c!corner,
@@ -184,21 +175,21 @@
\c!toffset=\zeropoint,
\c!boffset=\zeropoint]
-% for backgrounds
+%D For backgrounds and such:
-\getparameters
- [\??od] % for fast version
+\defineframed
+ [\??simplifiedframed]
[\c!frame=\v!off,
\c!depth=\zeropoint,
\c!offset=\v!overlay,
- %\c!component=,
- %\c!region=,
+ \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!backgroundcorner=\framedparameter\c!corner, % use \p_ here
\c!backgroundradius=\framedparameter\c!radius,
\c!backgrounddepth=\framedparameter\c!depth,
\c!framecorner=\framedparameter\c!corner,
@@ -210,13 +201,19 @@
\c!toffset=\zeropoint,
\c!boffset=\zeropoint]
-%D We will communicate through module specific variables, current
-%D framed parameters and some reserved dimension registers.
+\unexpanded\def\definesimplifiedframed[#1]% no settings
+ {\defineframed[#1][\??simplifiedframed]%
+ \expandafter\let\csname#1\endcsname\undefined}
+
+\expandafter\let\csname\??simplifiedframed\endcsname\undefined
+
+%D We will communicate through module specific variables, current framed
+%D 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
+\newdimen\d_framed_linewidth \let\ruledlinewidth\d_framed_linewidth % needed at lua end
\let\p_framed_frame \empty % \framedparameter\c!frame
\let\p_framed_backgroundoffset\empty
@@ -255,9 +252,9 @@
\def\pack_framed_filled_box_normal
{\vrule
- \!!width \d_framed_target_wd
- \!!height\d_framed_target_ht
- \!!depth \d_framed_target_dp
+ \s!width \d_framed_target_wd
+ \s!height\d_framed_target_ht
+ \s!depth \d_framed_target_dp
\relax}
\def\pack_framed_filled_box_radius
@@ -269,16 +266,10 @@
\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}%
- }}
+ {\back_ovalbox
+ \d_framed_target_wd \d_framed_target_ht \d_framed_target_dp
+ \d_framed_linewidth \p_framed_backgroundradius
+ \zerocount \plusone {\ifx\p_framed_backgroundcorner\v!round0\else\number\p_framed_backgroundcorner\fi}}
\def\pack_framed_stroked_box
{\edef\p_framed_framecorner{\framedparameter\c!framecorner}%
@@ -292,25 +283,17 @@
{\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}
+ \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}%
- }}
+ {\back_ovalbox
+ \d_framed_target_wd \d_framed_target_ht \d_framed_target_dp
+ \d_framed_linewidth \p_framed_frameradius
+ \plusone \zerocount {\ifx\p_framed_framecorner\v!round0\else\number\p_framed_framecorner\fi}}
% a lot of weird corners
%
@@ -370,8 +353,8 @@
\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:
+%D It won't be a surprise that we not only provide gray boxes, but also colored
+%D ones. Here it is:
\def\pack_framed_background_box_color
{\edef\p_framed_backgroundcolor{\framedparameter\c!backgroundcolor}%
@@ -387,10 +370,9 @@
%D overlaywidth, overlayheight, overlaydepth,
%D overlaycolor, overlaylinecolor, overlaylinewidth}
%D
-%D Before we define the macro that actually takes card of the
-%D backgrounds, we introduce overlays. An overlay is something
-%D that contrary to its name lays {\em under} the text. An
-%D example of an overlay definition is:
+%D Before we define the macro that actually takes card of the backgrounds, we
+%D introduce overlays. An overlay is something that contrary to its name lays {\em
+%D under} the text. An example of an overlay definition is:
%D
%D \startbuffer[tmp-1]
%D \defineoverlay
@@ -420,17 +402,16 @@
%D
%D \showsetup{defineoverlay}
%D
-%D This macro's definition is a bit obscure, due the many
-%D non||used arguments and the two step call that enable the
-%D setting of the width, height and depth variables.
-%D Multiple backgrounds are possible and are specified as:
+%D This macro's definition is a bit obscure, due the many non||used arguments and
+%D the two step call that enable the setting of the width, height and depth
+%D variables. Multiple backgrounds are possible and are specified as:
%D
%D \starttyping
%D \framed[background={one,two,three}]{Three backgrounds!}
%D \stoptyping
%D
-%D Most drawing packages only know width and height. Therefore
-%D the dimensions have a slightly different meaning here:
+%D Most drawing packages only know width and height. Therefore the dimensions have a
+%D slightly different meaning here:
%D
%D \startitemize[packed]
%D \item \type{\overlaywidth }: width of the overlay
@@ -452,9 +433,8 @@
\newtoks\everyoverlay
-%D An example of an initialization is the following (overlays
-%D can contain text and be executed under an regime where
-%D interlineskip is off).
+%D An example of an initialization is the following (overlays can contain text
+%D and be executed under an regime where interlineskip is off).
\installcorenamespace{overlay}
\installcorenamespace{overlaybuiltin}
@@ -515,8 +495,8 @@
\expandafter\secondoftwoarguments
\fi}
-%D The content of the box will be (temporary) saved in a box. We
-%D also have an extra box for backgrounds.
+%D The content of the box will be (temporary) saved in a box. We also have an
+%D extra box for backgrounds.
\newbox\b_framed_normal
\newbox\b_framed_extra
@@ -572,8 +552,8 @@
\expandafter\pack_framed_process_backgrounds
\fi#2}
-% beware, a backgroundbox can be empty which is another reason
-% why we set the width to zero instead of back-skipping
+%D Beware, a backgroundbox can be empty which is another reason why we set the
+%D width to zero instead of back-skipping.
\newdimen\framedbackgroundwidth
\newdimen\framedbackgroundheight
@@ -612,8 +592,7 @@
\egroup}}
\def\pack_framed_overlay_initialize_indeed
- {%\writestatus{!!!!}{<<<<<}%
- \edef\overlaywidth {\the\d_framed_target_wd\space}%
+ {\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 ?
@@ -624,8 +603,8 @@
\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 One can explictly insert the foreground box. For that purpose we introduce the
+%D overlay \type {foreground}.
%D
%D We predefine two already familiar backgrounds:
@@ -633,14 +612,13 @@
\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.
-
-%D Besides backgrounds (overlays) we also need some macros to
-%D draw outlines (ruled borders). Again we have to deal with
-%D square and round corners. The first category can be handled
-%D by \TEX\ itself, the latter one depends on the driver. This
-%D macro also support a negative offset.
+%D We can specify overlays as a comma separated list of overlays, a sometimes
+%D handy feature.
+%D
+%D Besides backgrounds (overlays) we also need some macros to draw outlines (ruled
+%D borders). Again we have to deal with square and round corners. The first category
+%D can be handled by \TEX\ itself, the latter one depends on the driver. This macro
+%D also support a negative offset.
\def\pack_framed_add_outline
{\setbox\b_framed_normal\hbox % rules on top of box
@@ -687,10 +665,10 @@
\dp\scratchbox\d_framed_target_dp
\box\scratchbox}
-\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}
+\def\pack_framed_t_rule{\hrule\s!height\d_framed_linewidth\kern-\d_framed_linewidth}
+\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\s!height\d_framed_linewidth}
+\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\s!width\d_framed_linewidth}
+\def\pack_framed_l_rule{\vrule\s!width\d_framed_linewidth\kern-\d_framed_linewidth}
\letvalue{\??framedtop \v!on \v!on}\pack_framed_t_rule
\letvalue{\??framedtop \v!off\v!on}\pack_framed_t_rule
@@ -710,10 +688,10 @@
% no overlapping rules
-\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}
+\def\pack_framed_t_rules{\hbox{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!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\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}}
+\def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth}
+\def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth}
\letvalue{\??framedtop \v!small\v!small}\pack_framed_t_rules
\letvalue{\??framedtop \v!off \v!small}\pack_framed_t_rules
@@ -744,11 +722,10 @@
% frame=off,rightframe=small,leftframe=small,topframe=small,bottomframe=on]
% {}
-%D The next few macros are probably the most misused ones in
-%D \CONTEXT. They deal with putting rules around boxes, provide
-%D backgrounds, offer alignment features, and some more. We
-%D start with defining some booleans. These give an impression
-%D of what we are going to take into account.
+%D The next few macros are probably the most misused ones in \CONTEXT. They deal
+%D with putting rules around boxes, provide backgrounds, offer alignment features,
+%D and some more. We start with defining some booleans. These give an impression of
+%D what we are going to take into account.
% todo : \c_framed_hasoffset
% faster : \let\c_framed_hasoffset\falseconditional
@@ -766,67 +743,72 @@
%D \macros
%D {framed, setupframed}
%D
-%D Ruled boxes are typeset using \type{\framed}. This command
-%D is quite versatile and, although some users will probably
-%D seldom use it, one cannot overlook its features.
+%D Ruled boxes are typeset using \type{\framed}. This command is quite versatile
+%D and, although some users will probably seldom use it, one cannot overlook its
+%D features.
%D
-%D \showsetup{setupframed}
-%D \showsetup{framed}
+%D \showsetup{setupframed}
+%D \showsetup{framed}
%D
-%D This general macro is a special version of an even more
-%D general case, that can easily be linked into other macros
-%D that need some kind of framing. The local version is called
-%D with an extra parameter: the variable identifier. The reason
-%D for passing this identifier between brackets lays in the
-%D mere fact that this way we can use the optional argument
-%D grabbers.
+%D This general macro is a special version of an even more general case, that can
+%D easily be linked into other macros that need some kind of framing. The local
+%D version is called with an extra parameter: the variable identifier. The reason
+%D for passing this identifier between brackets lays in the mere fact that this way
+%D we can use the optional argument grabbers.
\def\defaultframeoffset{.25ex}
-\def\presetlocalframed [#1]{\letvalue {#1\s!parent}\??framed}
-\def\inheritlocalframed[#1]#2[#3]{\setevalue{#1\s!parent}{#3}}
+\installcorenamespace{regularframedlevel}
+
+\unexpanded\def\installregularframed#1%
+ {\defineframed[#1]}
+
+\unexpanded\def\presetlocalframed[#1]%
+ {\defineframed[#1]}
-\presetlocalframed[\??ol]
+% \presetlocalframed[\??framed]
-\newcount\framednesting
+\newcount\c_pack_framed_nesting
+
+\unexpanded\def\pack_framed_process_framed[#1]%
+ {\bgroup
+ \iffirstargument % faster
+ \setupcurrentframed[#1]% here !
+ \fi
+ \pack_framed_process_indeed}
\unexpanded\def\framed
{\bgroup
- \advance\framednesting\plusone
- \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol
- \dodoubleempty\pack_framed_process[\??ol:\the\framednesting]}
+ \advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \dosingleempty\pack_framed_process_framed}
\unexpanded\def\startframed
{\dosingleempty\pack_framed_start_framed}
\def\pack_framed_start_framed[#1]%
{\bgroup
- \advance\framednesting\plusone
- \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol
+ \advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
\iffirstargument\secondargumenttrue\fi % dirty trick
- \pack_framed_process[\??ol:\the\framednesting][#1]%
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \pack_framed_process_framed[#1]% can be inlined
\bgroup}
\let\stopframed\egroup
-\unexpanded\def\setupframed
- {\dodoubleempty\dosetupframed}
-
-\unexpanded\def\normalframedwithsettings
+\unexpanded\def\normalframedwithsettings[#1]%
{\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
-
-\def\dosetupframed[#1][#2]%
- {\ifsecondargument
- \getparameters[\??ol#1][#2]%
- \else
- \getparameters[\??ol][#1]%
- \fi}
+ \advance\c_pack_framed_nesting\plusone
+ \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed
+ \bgroup
+ \edef\currentframed{>\the\c_pack_framed_nesting}%
+ \pack_framed_initialize
+ \setupcurrentframed[#1]%
+ \pack_framed_process_indeed}
%D \startbuffer
%D \setupframed [framecolor=yellow] \framed{A}
@@ -846,13 +828,11 @@
%D \macros
%D {ifinframed}
%D
-%D The normal case first presets all parameters and next starts
-%D looking for the user supplied ones. The first step is
-%D omitted in the local case, because these are preset at
-%D declaration time and keep their values unless explictly
-%D changed. By presetting the variables everytime the normal
-%D command is called, we can use this command nested, without
-%D the unwanted side effect of inheritance. The boolean is
+%D The normal case first presets all parameters and next starts looking for the user
+%D supplied ones. The first step is omitted in the local case, because these are
+%D preset at declaration time and keep their values unless explictly changed. By
+%D presetting the variables everytime the normal command is called, we can use this
+%D command nested, without the unwanted side effect of inheritance. The boolean is
%D used to speed up the color stack.
\newif\ifinframed
@@ -862,7 +842,8 @@
\unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4
{\bgroup
- \pack_framed_initialize{#1}%
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
\setbox\b_framed_normal\hbox{#4}%
\edef\p_framed_region{\framedparameter\c!region}%
\ifx\p_framed_region\v!yes % maybe later named
@@ -880,8 +861,7 @@
\d_framed_linewidth\p_framed_rulethickness\relax
\fi
\pack_framed_add_outline % real or invisible frame
- \fi \fi
- \fi
+ \fi\fi
\ifx\p_framed_background\empty \else
\edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
\d_framed_backgroundoffset
@@ -897,12 +877,13 @@
\box\b_framed_normal
\egroup}
-%D The next macro uses a box and takes its natural width and
-%D height so these can better be correct.
+%D The next macro uses a box and takes its natural width and height so these
+%D can better be correct.
-\def\localbackgroundframed#1#2#3% namespace component box
+\unexpanded\def\localbackgroundframed#1#2#3% namespace component box
{\bgroup
- \pack_framed_initialize{#1}%
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
\setbox\b_framed_normal\box#3%
\edef\p_framed_region{\framedparameter\c!region}%
\ifx\p_framed_region\v!yes % maybe later named
@@ -917,7 +898,7 @@
\d_framed_linewidth\p_framed_rulethickness\relax
\fi
\pack_framed_add_outline % real or invisible frame
- \fi \fi
+ \fi\fi
\ifx\p_framed_background\empty \else
\edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
\d_framed_backgroundoffset
@@ -955,35 +936,36 @@
\unexpanded\def\localframed
{\bgroup
- \dodoubleempty\pack_framed_process}
+ \dodoubleempty\pack_framed_local}
-\unexpanded\def\pack_framed_process[#1][#2]% assumes a \dodoubleempty (slows down), also should have leading \bgroup
+\unexpanded\def\pack_framed_local[#1][#2]%
{\bgroup
- \pack_framed_initialize{#1}%
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
\ifsecondargument % faster
- \getparameters[\currentframed][#2]% here !
+ \setupcurrentframed[#2]% here !
\fi
\pack_framed_process_indeed}
\unexpanded\def\directlocalframed[#1]% no optional
{\bgroup
\bgroup
- \pack_framed_initialize{#1}%
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
\pack_framed_process_indeed}
\unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between)
{\bgroup
\bgroup
- \pack_framed_initialize{#1}%
- \getparameters[\currentframed][#2]% here !
+ \edef\currentframed{#1}%
+ \pack_framed_initialize
+ \setupcurrentframed[#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\pack_framed_process_indeed
{\d_framed_frameoffset\framedparameter\c!frameoffset
\edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
@@ -1038,78 +1020,28 @@
\settrue\c_framed_has_format
\dosetraggedcommand\localformat % not that fast
\fi
- \ifx\localoffset\v!none
- \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\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
- \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
- \letframedparameter\c!offset\defaultframeoffset % brrr
+ \csname\??framedoffsetalternative
+ \ifcsname\??framedoffsetalternative\localoffset\endcsname
+ \localoffset
\else
- \let\defaultframeoffset\localoffset
+ \s!unknown
\fi
- \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
- \ifconditional\c_framed_has_format
- \settrue\c_framed_has_width
- \d_framed_width\hsize
+ \endcsname
+ \csname\??framedwidthalternative
+ \ifcsname\??framedwidthalternative\localwidth\endcsname
+ \localwidth
\else
- \setfalse\c_framed_has_width
+ \s!unknown
\fi
- \else\ifx\localwidth\v!fit
- \ifconditional\c_framed_has_format
- \settrue\c_framed_has_width
- \d_framed_width\hsize
+ \endcsname
+ \csname\??framedheightalternative
+ \ifcsname\??framedheightalternative\localheight\endcsname
+ \localheight
\else
- \setfalse\c_framed_has_width
+ \s!unknown
\fi
- \else\ifx\localwidth\v!fixed % equals \v!fit but no shapebox
- \ifconditional\c_framed_has_format
- \settrue\c_framed_has_width
- \d_framed_width\hsize
- \else
- \setfalse\c_framed_has_width
- \fi
- \else\ifx\localwidth\v!broad
- \settrue\c_framed_has_width
- \d_framed_width\hsize
- \else\ifx\localwidth\v!local
- \settrue\c_framed_has_width
- \setlocalhsize
- \d_framed_width\localhsize
- \else
- \settrue\c_framed_has_width
- \d_framed_width\localwidth
- \fi\fi\fi\fi\fi
- \ifx\localheight\empty % fallback to fit
- \setfalse\c_framed_has_height
- \else\ifx\localheight\v!fit
- \setfalse\c_framed_has_height
- \else\ifx\localheight\v!broad
- \setfalse\c_framed_has_height
- \else
- \settrue\c_framed_has_height
- \d_framed_height\localheight
- \fi\fi\fi
+ \endcsname
+ % the next check could move to heightalternative
\ifconditional\c_framed_has_height
% obey user set height, also downward compatible
\else
@@ -1132,15 +1064,14 @@
% i.e. disable (colsetbackgroundproblemintechniek)
\advance\d_framed_width -2\d_framed_local_offset
\advance\d_framed_height -2\d_framed_local_offset
- \ifx\localstrut\v!no
- \setfalse\c_framed_has_strut
- \else\ifx\localstrut\v!global
- \setstrut
- \else\ifx\localstrut\v!local
- \setfontstrut
- \else
- \setstrut
- \fi\fi\fi
+ \csname\??framedstrutalternative
+ \ifcsname\??framedstrutalternative\localstrut\endcsname
+ \localstrut
+ \else
+ \s!unknown
+ \fi
+ \endcsname
+ % the next check could move to strutalternative
\ifconditional\c_framed_has_strut
\let\localbegstrut\begstrut
\let\localendstrut\endstrut
@@ -1219,6 +1150,136 @@
\afterassignment\pack_framed_restart
\setbox\b_framed_normal\next}
+% alternatives for width, height, strut and offset
+
+\installcorenamespace{framedwidthalternative}
+\installcorenamespace{framedheightalternative}
+\installcorenamespace{framedstrutalternative}
+\installcorenamespace{framedoffsetalternative}
+
+% widths
+
+\setvalue{\??framedwidthalternative\empty}%
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!fit}%
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!fixed}% equals \v!fit but no shapebox
+ {\ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
+ \else
+ \setfalse\c_framed_has_width
+ \d_framed_width\zeropoint
+ \fi}
+
+\setvalue{\??framedwidthalternative\v!broad}%
+ {\settrue\c_framed_has_width
+ \d_framed_width\hsize}
+
+\setvalue{\??framedwidthalternative\v!max}% idem broad
+ {\settrue\c_framed_has_width
+ \d_framed_width\hsize}
+
+\setvalue{\??framedwidthalternative\v!local}%
+ {\settrue\c_framed_has_width
+ \setlocalhsize
+ \d_framed_width\localhsize}
+
+\setvalue{\??framedwidthalternative\s!unknown}%
+ {\settrue\c_framed_has_width
+ \d_framed_width\localwidth}
+
+% heights
+
+\setvalue{\??framedheightalternative\empty}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!fit}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!broad}%
+ {\setfalse\c_framed_has_height
+ \d_framed_height\zeropoint}
+
+\setvalue{\??framedheightalternative\v!max}%
+ {\settrue\c_framed_has_height
+ \d_framed_height\vsize}
+
+\setvalue{\??framedheightalternative\s!unknown}%
+ {\settrue\c_framed_has_height
+ \d_framed_height\localheight}
+
+% struts
+
+\setvalue{\??framedstrutalternative\v!no}%
+ {\setfalse\c_framed_has_strut}
+
+\setvalue{\??framedstrutalternative\v!global}%
+ {\setstrut}
+
+\setvalue{\??framedstrutalternative\v!local}%
+ {\setfontstrut}
+
+\setvalue{\??framedstrutalternative\v!yes}%
+ {\setstrut}
+
+\setvalue{\??framedstrutalternative\s!unknown}%
+ {\setstrut}
+
+% offsets
+
+\setvalue{\??framedoffsetalternative\v!none}%
+ {\setfalse\c_framed_has_offset
+ \setfalse\c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
+ \d_framed_local_offset\d_framed_linewidth}
+
+\setvalue{\??framedoffsetalternative\v!overlay}%
+ {% \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}
+
+% \setvalue{\??framedoffsetalternative\v!strut}%
+% {\setfalse\c_framed_has_offset
+% \settrue \c_framed_has_strut
+% \settrue \c_framed_is_overlaid
+% \d_framed_local_offset\zeropoint}
+
+\setvalue{\??framedoffsetalternative\v!default}% new per 2-6-2000
+ {\settrue \c_framed_has_offset
+ \settrue \c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
+ \let\localoffset\defaultframeoffset
+ \letframedparameter\c!offset\defaultframeoffset % brrr
+ \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
+
+\setvalue{\??framedoffsetalternative\s!unknown}%
+ {\settrue \c_framed_has_offset
+ \settrue \c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
+ \let\defaultframeoffset\localoffset
+ \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax}
+
+% so far for alternatives
+
\let\pack_framed_stop_orientation\relax
\def\pack_framed_restart
@@ -1227,18 +1288,17 @@
\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
-%D is, some assignments to \type{\next} will never occur.
-%D Nevertheless we implement the whole scheme, if not for
-%D future extensions.
+%D Carefull analysis of this macro will learn us that not all branches in the last
+%D conditionals can be encountered, that is, some assignments to \type{\next} will
+%D never occur. Nevertheless we implement the whole scheme, if not for future
+%D extensions.
%D \macros
%D {doassigncheckedframeoffset}
%D
%D Offset helper (see menus):
-\def\doassigncheckedframeoffset#1#2%
+\def\doassigncheckedframeoffset#1#2% could be a fast \csname .. \endcsname
{\edef\checkedframeoffset{#2}%
#1%
\ifx\checkedframeoffset\empty \zeropoint\else
@@ -1253,11 +1313,10 @@
%D \macros
%D {ifreshapeframebox}
%D
-%D The last few lines tell what to do after the content of the
-%D box is collected and passed to the next macro. In the case
-%D of a fixed width and centered alignment, the content is
-%D evaluated and used to determine the most natural width. The
-%D rest of the code deals with backgrounds and frames.
+%D The last few lines tell what to do after the content of the box is collected and
+%D passed to the next macro. In the case of a fixed width and centered alignment,
+%D the content is evaluated and used to determine the most natural width. The rest
+%D of the code deals with backgrounds and frames.
\newif\ifreshapeframebox \reshapeframeboxtrue
@@ -1323,8 +1382,8 @@
\else
\pack_framed_finish_c
\fi\fi\fi
- \ifconditional\boxcontentneedsprocessing
- \mkdoprocessboxcontents\b_framed_normal
+ \ifconditional\page_postprocessors_needed_box
+ \page_postprocessors_linenumbers_box\b_framed_normal
\fi
\else
\pack_framed_finish_c
@@ -1570,9 +1629,9 @@
\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.
+%D The last conditional takes care of the special situation of in||line \inframed
+%D [height=3cm] {framed} boxes. Such boxes have to be \inframed {aligned} with the
+%D running text.
\unexpanded\def\inframed
{\dosingleempty\pack_framed_inline}
@@ -1585,15 +1644,14 @@
\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 When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background,
+%D but no content, so actually we have a sort of phantom framed box.
%D \macros
%D {mframed, minframed}
%D
-%D When Tobias asked how to frame mathematical elements in
-%D formulas, Taco's posted the next macro:
+%D When Tobias asked how to frame mathematical elements in formulas, Taco's posted the
+%D next macro:
%D
%D \starttyping
%D \def\mframed#1%
@@ -1605,9 +1663,8 @@
%D \fi}
%D \stoptyping
%D
-%D Because \type {\ifinner} does not (always) reports what
-%D one would expect, we move the test to the outer level. We
-%D also want to pass arguments,
+%D Because \type {\ifinner} does not (always) reports what one would expect, we move the
+%D test to the outer level. We also want to pass arguments,
%D
%D \starttyping
%D \def\mframed%
@@ -1626,8 +1683,8 @@
%D \fi}
%D \stoptyping
%D
-%D Still better is the next alternative, if only because it
-%D takes care of setting the super- and subscripts styles
+%D Still better is the next alternative, if only because it takes care of setting the super-
+%D and subscripts styles
\newcount\c_framed_mstyle
@@ -1637,22 +1694,6 @@
\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
@@ -1678,8 +1719,7 @@
\definemathframed[mframed]
\definemathframed[inmframed][\c!location=\v!low]
-%D So instead of the rather versatile \type {\framed}, we ue
-%D the \type {\mframed}.
+%D So instead of the rather versatile \type {\framed}, we use \type {\mframed}:
%D
%D \startbuffer
%D \startformula
@@ -1700,11 +1740,9 @@
%D
%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
-%D preserve the proper spacing, the \type {offset} is set to
-%D \type {overlay} and \type {frameoffset} is used used
-%D instead.
+%D As usual, one can specify in what way the text should be framed. One should be
+%D aware of the fact that, inorder to preserve the proper spacing, the \type
+%D {offset} is set to \type {overlay} and \type {frameoffset} is used used instead.
%D
%D \startbuffer
%D \startformula
@@ -1714,13 +1752,11 @@
%D
%D \typebuffer \getbuffer
%D
-%D For inline use, we also provide the \type {\inmframed}
-%D alternative: we want $x \times \inmframed{y}$ in inline
-%D math, right?
+%D For inline use, we also provide the \type {\inmframed} alternative: we want $x
+%D \times \inmframed{y}$ in inline math, right?
-%D This previous framing macros needs a lot of alternatives for
-%D putting rules around boxes, inserting offsets and aligning
-%D text. Each step is handled by separate macros.
+%D This previous framing macros needs a lot of alternatives for putting rules around
+%D boxes, inserting offsets and aligning text. Each step is handled by separate macros.
\newdimen\d_framed_applied_offset
\newdimen\d_framed_loffset
@@ -1760,8 +1796,8 @@
\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.
+%D Let's hope that the next few examples show us enough of what needs to be
+%D done by the auxiliary macros.
%D
%D \startbuffer
%D \framed[height=1cm,offset=.5cm] {rule based learning}
@@ -1815,25 +1851,21 @@
%D \hbox{\dontcomplain\getbuffer}
%D \stoplinecorrection
%D
-%D So now we're ready for the complicated stuff. We distinguish
-%D between borders with straight lines and those with round
-%D corners. When using the first alternative it is possible to
-%D turn off one or more lines. More fancy shapes are also
-%D possible by specifying dedicated backgrounds. Turning lines
-%D on and off is implemented as efficient as possible and as a
-%D result is interface language dependant. This next
-%D implementation evolved from simpler ones. It puts for
-%D instance the rules on top of the content and provides
-%D additional offset capabilities. The lot of calls to other
-%D macros makes this mechanism not that easy to comprehend.
-
-%D We handle left, right or middle alignment as well as fixed
-%D or free widths and heights. Each combination gets its own
-%D macro.
-
-%D The following code handles one-liners: \type{align={line,flushright}}.
-%D Beware, since we entered a group and either or not grab the next
-%D bgroup token, we need to finish the group in the oneliner mode.
+%D So now we're ready for the complicated stuff. We distinguish between borders with
+%D straight lines and those with round corners. When using the first alternative it
+%D is possible to turn off one or more lines. More fancy shapes are also possible by
+%D specifying dedicated backgrounds. Turning lines on and off is implemented as
+%D efficient as possible and as a result is interface language dependant. This next
+%D implementation evolved from simpler ones. It puts for instance the rules on top
+%D of the content and provides additional offset capabilities. The lot of calls to
+%D other macros makes this mechanism not that easy to comprehend.
+%D
+%D We handle left, right or middle alignment as well as fixed or free widths and
+%D heights. Each combination gets its own macro.
+%D
+%D The following code handles one-liners: \type {align={line,flushright}}. Beware,
+%D since we entered a group and either or not grab the next bgroup token, we need to
+%D finish the group in the oneliner mode.
\ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi
@@ -2013,11 +2045,10 @@
\localstrut
\doformatonelinerbox}
-%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
-%D formatting. Watch the visualized struts. \footnote {Here we
-%D used \type {\showstruts}.}
+%D On the next page we show some examples of how these macros come into action. The
+%D examples show us how \type {fit}, \type {broad} dimensions influence the
+%D formatting. Watch the visualized struts. \footnote {Here we used \type
+%D {\showstruts}.}
%D
%D \startpostponing
%D \bgroup
@@ -2072,9 +2103,8 @@
%D \macros
%D {framednoflines, framedlastlength}
%D
-%D It is possible to let the frame macro calculate the width
-%D of a centered box automatically (\type {fit}). When
-%D doing so, we need to reshape the box:
+%D It is possible to let the frame macro calculate the width of a centered box
+%D automatically (\type {fit}). When doing so, we need to reshape the box:
\newcount\framednoflines
\newdimen\framedfirstheight
@@ -2106,13 +2136,12 @@
% \startformula \startalign \NC \int_01 \NC B \NR \intertext{test} \NC \int_01 \NC D \NR \stopalign \stopformula
% \stopTEXpage
-%D The examples on the next page show how one can give the
-%D frame as well as the background an additional offset and
-%D even a bit more depth. The blue outline is the frame, the
-%D red box is the background and the small black outline is the
-%D visualization of the resulting box, that is, we applied
-%D \type{\ruledhbox} to the result.
-
+%D The examples on the next page show how one can give the frame as well as the
+%D background an additional offset and even a bit more depth. The blue outline is
+%D the frame, the red box is the background and the small black outline is the
+%D visualization of the resulting box, that is, we applied \type {\ruledhbox} to
+%D the result.
+%D
%D \startpostponing
%D \bgroup
%D \unprotect
@@ -2162,9 +2191,8 @@
%D \egroup
%D \stoppostponing
-%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.
+%D We can draw lines from left to right and top to bottom by using the normal \type
+%D {\hairline} command. Both directions need a different treatment.
%D
%D \startbuffer
%D \framed[width=4cm] {alfa\hairline beta\hairline gamma}
@@ -2178,26 +2206,8 @@
%D \hbox{\getbuffer}
%D \stoplinecorrection
%D
-%D These macros try to adapt their behaviour as good as
-%D possible to the circumstances and act as natural as
-%D possible.
-
-% \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
+%D These macros try to adapt their behaviour as good as possible to the circumstances
+%D and act as natural as possible.
\unexpanded\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth
{\begingroup
@@ -2207,13 +2217,13 @@
\nointerlineskip
\kern\scratchoffset
\dontleavehmode
- \hrule\!!height\d_framed_linewidth\!!depth\zeropoint
+ \hrule\s!height\d_framed_linewidth\s!depth\zeropoint
\par
\kern-\d_framed_linewidth
\dontleavehmode
- \hbox to \zeropoint{\normalhss\vrule\!!height\d_framed_linewidth\!!depth\zeropoint\!!width\scratchwidth}%
+ \hbox to \zeropoint{\normalhss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}%
\hfill
- \hbox to \zeropoint{\vrule\!!height\d_framed_linewidth\!!depth\zeropoint\!!width\scratchwidth\normalhss}%
+ \hbox to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\normalhss}%
\par
\nointerlineskip
\kern\scratchoffset
@@ -2223,32 +2233,29 @@
\localbegstrut
\endgroup}
-% todo:
-
\unexpanded\def\pack_framed_hboxed_hairline % use framed dimen
{\bgroup
- \dimen2=\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
+ \scratchoffset\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
+ \dimen\scratchheight\dimexpr\localheight/\plustwo+\strutdp-\plustwo\d_framed_linewidth\relax
+ \dimen\scratchdepth \dimexpr\localheight/\plustwo-\strutdp+\plustwo\d_framed_linewidth\relax
\else
- \dimen4\dimexpr\strutht+\dimen2\relax
- \dimen6\dimexpr\strutdp+\dimen2\relax
+ \dimen\scratchheight\dimexpr\strutht+\scratchoffset\relax
+ \dimen\scratchdepth \dimexpr\strutdp+\scratchoffset\relax
\fi
\unskip
\setbox\scratchbox\hbox
- {\hskip\dimen2
- \vrule\!!height\dimen4\!!depth\dimen6\!!width\d_framed_linewidth
- \hskip\dimen2}%
+ {\hskip\scratchoffset
+ \vrule\s!height\dimen\scratchheight\s!depth\dimen\scratchdepth\s!width\d_framed_linewidth
+ \hskip\scratchoffset}%
\ht\scratchbox\strutht
\dp\scratchbox\strutdp
\box\scratchbox
\ignorespaces
\egroup}
-%D The argument of the frame command accepts \type{\\} as a
-%D sort of newline signal. In horizontal boxes it expands to a
-%D space.
+%D The argument of the frame command accepts \type{\\} as a sort of newline signal. In
+%D horizontal boxes it expands to a space.
\unexpanded\def\pack_framed_vboxed_newline
{\endgraf\ignorespaces}
@@ -2256,10 +2263,9 @@
\unexpanded\def\pack_framed_hboxed_newline
{\unskip\normalspace\ignorespaces}
-%D We can set each rule on or off. The default setting is
-%D inherited from \type{frame}. An earlier implementation
-%D use a bit different approach, but the new one seems more
-%D natural:
+%D We can set each rule on or off. The default setting is inherited from
+%D \type {frame}. An earlier implementation use a bit different approach, but the new
+%D one seems more natural:
%D
%D \bgroup
%D \setuptyping[margin=0pt]
@@ -2299,10 +2305,9 @@
%D \macros
%D {startframedtext, setupframedtexts, defineframedtext}
%D
-%D The general framing command we discussed previously, is not
-%D entirely suited for what we call framed texts, as for
-%D instance used in intermezzo's. The next examples show what
-%D we have in mind.
+%D The general framing command we discussed previously, is not entirely suited for
+%D what we call framed texts, as for instance used in intermezzo's. The next
+%D examples show what we have in mind.
%D
%D \startbuffer[framed-0]
%D \setupframedtexts
@@ -2364,8 +2369,8 @@
%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-3] \egroup
%D \bgroup \setuptyping[margin=0pt] \getbuffer[framed-4] \egroup
%D
-%D Here we can see that we have a predefined framed text class
-%D as well as the tools for defining our own. So we have:
+%D Here we can see that we have a predefined framed text class as well as the
+%D tools for defining our own. So we have:
%D
%D \showsetup{setupframedtexts}
%D
@@ -2388,7 +2393,7 @@
\let\setupframedtexts\setupframedtext
\setupframedtext
- [\c!width=0.75\hsize,
+ [\c!width=.75\hsize,
\c!height=\v!fit,
\c!align=\v!yes,
%\c!top=,
@@ -2415,7 +2420,7 @@
%\c!foregroundstyle=,
%\c!background=,
%\c!backgroundcolor=,
- \c!backgroundscreen=\@@rsscreen,
+ \c!backgroundscreen=\defaultbackgroundscreen,
\c!linecorrection=\v!on,
\c!depthcorrection=\v!on,
\c!margin=\v!standard]
@@ -2461,7 +2466,6 @@
\hsize\localhsize
% \insidefloattrue % ? better
\normalexpanded{\switchtobodyfont[\framedtextparameter\c!bodyfont]}%
-% \startcolor[\framedtextparameter\c!color]%
\letframedtextparameter\c!strut\v!no
\inheritedframedtextframed\bgroup
\let\\=\endgraf
@@ -2471,9 +2475,8 @@
\setupindenting[\framedtextparameter\c!indenting]%
\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.
+%D The \type {none} option is handy for nested usage, as in the presentation
+%D styles, where we don't want interference.
\defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext]
@@ -2482,7 +2485,6 @@
\removelastskip
\doif{\framedtextparameter\c!depthcorrection}\v!on\pack_framed_text_stop_depth_correction
\stopboxedcontent
-% \stopcolor
\ifconditional\c_framed_text_location_none
\egroup
\box\b_framed_normal
@@ -2551,8 +2553,8 @@
%D \egroup
%D \stoptyping
-%D The simple brace (or group) delimited case is typeset
-%D slightly different and is not aligned.
+%D The simple brace (or group) delimited case is typeset slightly different
+%D and is not aligned.
\unexpanded\def\pack_framed_text_direct#1%
{\bgroup
@@ -2579,7 +2581,8 @@
\egroup
\egroup}
-\defineframedtext[\v!framedtext]
+\defineframedtext
+ [\v!framedtext]
%D \macros
%D {defineframed}
@@ -2588,47 +2591,44 @@
%D
%D \showsetup{defineframed}
%D
-%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance
-%D model instead of passing a combination of arguments. This also
-%D also simplified the \type {\setupframed} command. There are
-%D certainly more places where such improvements can be made.
-
-% actually, this can be another command handler .. todo
+%D As suggested by Wolfgang we can now use the new \MKIV\ inheritance model instead
+%D of passing a combination of arguments. This also also simplified the \type
+%D {\setupframed} command. There are certainly more places where such improvements
+%D can be made.
-\unexpanded\def\defineframed
- {\dotripleempty\pack_framed_define}
+\appendtoks
+ \ifcsname\??regularframedlevel\currentframed\endcsname
+ % already defined, keeps settings
+ \else
+ \expandafter\newcount\csname\??regularframedlevel\currentframed\endcsname
+ \fi
+\to \everypresetframed
-\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
- \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
+\appendtoks
+ \setuevalue\currentframed{\pack_framed_defined_process[\currentframed]}%
+\to \everydefineframed
-\newcount\c_framed_crap
+\newcount\c_temp_framed_crap
\unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent)
{\bgroup
- \ifcsname\??ol:#1\endcsname
- \expandafter\let\expandafter\c_framed_temp\csname\??ol:#1\endcsname
+ \ifcsname\??regularframedlevel#1\endcsname
+ \expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname
\else
- \let\c_framed_temp\c_framed_crap
+ \let\c_pack_framed_temp\c_temp_framed_crap
+ \fi
+ \advance\c_pack_framed_temp\plusone
+ \expandafter\def\csname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed
+ \bgroup
+ \edef\currentframed{#1>\the\c_pack_framed_temp}%
+ \pack_framed_initialize
+ \dosingleempty\pack_framed_defined_process_indeed}
+
+\def\pack_framed_defined_process_indeed[#1]%
+ {\iffirstargument % faster
+ \setupcurrentframed[#1]% here !
\fi
- \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]}
+ \pack_framed_process_indeed}
\let\placeframed\pack_framed_defined_process % new per 2012/04/23
@@ -2640,8 +2640,8 @@
%D
%D but the existing one is ok as well (less csname messy too).
-%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 New, for the moment private; let's see when GB finds out about this one and its
+%D obscure usage. It's used in:
%D
%D \startbuffer
%D \defineframedtext
@@ -2675,21 +2675,17 @@
%D
%D \typebuffer
-% to be redone
+\installcorenamespace{framedcontent}
-\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}
+\installframedcommandhandler \??framedcontent {framedcontent} \??framedcontent
-\presetlocalframed[\??fc]
-
-\getparameters
- [\??fc]
+\setupframedcontent
[\c!leftoffset=\zeropoint,
- \c!rightoffset=\framedcontentparameter\c!leftoffset,
+ %\c!rightoffset=\framedcontentparameter\c!leftoffset,
+ \c!rightoffset=\scratchleftoffset,
\c!topoffset=\zeropoint,
- \c!bottomoffset=\framedcontentparameter\c!topoffset,
+ %\c!bottomoffset=\framedcontentparameter\c!topoffset,
+ \c!bottomoffset=\scratchtopoffset,
\c!strut=\v!no,
%\c!linecorrection=\v!no,
%\c!left=,
@@ -2697,19 +2693,6 @@
%\c!width=\v!fit,
\c!offset=\v!overlay]
-\unexpanded\def\defineframedcontent
- {\dodoubleempty\dodefineframedcontent}
-
-\def\dodefineframedcontent[#1][#2]%
- {\getparameters[\??fc#1][\s!parent=\??fc,#2]}
-
-\unexpanded\def\setupframedcontent
- {\dodoubleempty\dosetupframedcontent}
-
-\def\dosetupframedcontent[#1][#2]%
- {\def\docommand##1{\getparameters[\??fc##1][#2]}%
- \processcommacommand[#1]\docommand}
-
\unexpanded\def\startframedcontent
{\dosingleempty\pack_framed_start_content}
@@ -2727,11 +2710,15 @@
{\setbox\b_framed_normal\hbox\bgroup
\setlocalhsize
\hsize\localhsize
- \advance\hsize\dimexpr-\framedcontentparameter\c!leftoffset-\framedcontentparameter\c!rightoffset \relax
- \advance\vsize\dimexpr-\framedcontentparameter\c!topoffset -\framedcontentparameter\c!bottomoffset\relax
- \hskip\framedcontentparameter\c!leftoffset
+ \scratchleftoffset \framedcontentparameter\c!leftoffset \relax
+ \scratchrightoffset \framedcontentparameter\c!rightoffset \relax
+ \scratchtopoffset \framedcontentparameter\c!topoffset \relax
+ \scratchbottomoffset\framedcontentparameter\c!bottomoffset\relax
+ \advance\hsize\dimexpr-\scratchleftoffset-\scratchrightoffset \relax
+ \advance\vsize\dimexpr-\scratchtopoffset -\scratchbottomoffset\relax
+ \hskip\scratchleftoffset
\vbox\bgroup
- \vskip\framedcontentparameter\c!topoffset
+ \vskip\scratchtopoffset
\vbox\bgroup
\forgetall
\blank[\v!disable]}
@@ -2739,9 +2726,9 @@
\def\pack_framed_stop_content_indeed
{\removelastskip
\egroup
- \vskip\framedcontentparameter\c!bottomoffset
+ \vskip\scratchbottomoffset
\egroup
- \hskip\framedcontentparameter\c!rightoffset
+ \hskip\scratchrightoffset
\egroup
\doif{\framedcontentparameter\c!width}\v!fit
{\letframedcontentparameter\c!width\v!fixed}% no shapebox
@@ -2753,7 +2740,7 @@
% plaats ?
\ifdone\startlinecorrection\fi
\framedcontentparameter\c!left % new
- \localframed[\??fc\currentframedcontent]{\box\b_framed_normal}% hm
+ \inheritedframedcontentframed{\box\b_framed_normal}% hm
\framedcontentparameter\c!right % new
\ifdone\stoplinecorrection\fi
\egroup}
@@ -2763,57 +2750,15 @@
\setuplinewidth
[\v!medium]
-% We could omit the empty setings but that is some 10% slower due to
-% extra testing in the chain.
+%D A Goodie:
-\setupframed
- [\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=\@@rsscreen,
- %\c!backgroundcolor=,
- \c!backgroundoffset=\zeropoint,
- %\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!region=,
- %\c!align=,
- \c!bottom=\vss,
- %\c!top=,
- \c!autostrut=\v!yes,
- \c!location=\v!normal,
- %\c!orientation=,
- \c!autowidth=\v!yes,
- %\c!setups=,
- \c!strut=\v!yes,
- %\c!loffset=\zeropoint,
- %\c!roffset=\zeropoint,
- %\c!toffset=\zeropoint,
- ]%\c!boffset=\zeropoint]
+\def\v!unframed{unframed}
-\setupscreens
- [\c!screen=0.95]
+\defineframed
+ [\v!unframed]
+ [\c!frame=\v!off,
+ \c!rulethickness=\zeropoint,
+ \c!foregroundstyle=\framedparameter\c!style,
+ \c!foregroundcolor=\framedparameter\c!color]
\protect \endinput
diff --git a/tex/context/base/page-app.mkiv b/tex/context/base/page-app.mkiv
index df9607daa..0cf83592d 100644
--- a/tex/context/base/page-app.mkiv
+++ b/tex/context/base/page-app.mkiv
@@ -34,6 +34,7 @@
[fittingpage]
[\c!textstate=\v!empty,
\c!doublesided=\v!no,
+ \c!location=\v!top, % no topskip
\c!pagestate=\fittingpageparameter\c!pagestate]%
\definelayout
@@ -180,14 +181,16 @@
%D \starttext \pagefigure[two.1] \stoptext
%D \stoptyping
+\defineexternalfigure[\v!page:\v!figure][\c!offset=\v!overlay] % we force a parent
+
\unexpanded\def\startpagefigure
{\dodoubleempty\page_figures_start}
\def\page_figures_start[#1][#2]%
{\bgroup
- \getparameters[\??ex][\c!offset=\v!overlay,#2]%
- \startTEXpage[\c!offset=\@@exoffset]%
- \externalfigure[#1][#2]\ignorespaces} % so we can put some text below the graphic
+ \setupexternalfigure[\v!page:\v!figure][\c!offset=\v!overlay,#2]%
+ \startTEXpage[\c!offset=\externalfigureparameter\c!offset]%
+ \externalfigure[#1][\v!page:\v!figure]\ignorespaces} % so we can put some text below the graphic
\unexpanded\def\stoppagefigure
{\stopTEXpage
diff --git a/tex/context/base/page-bck.mkiv b/tex/context/base/page-bck.mkiv
index 100c186dd..cc4db92fb 100644
--- a/tex/context/base/page-bck.mkiv
+++ b/tex/context/base/page-bck.mkiv
@@ -11,19 +11,18 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% 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.
+% Currently the text cells are fakes and no (foreground) frames which makes sense
+% as order might matter e.g. is text sticks in other cells. The page, text etc
+% areas do support foreground order change.
\writestatus{loading}{ConTeXt Page Macros / Backgrounds}
\unprotect
-%D For special purposes, users can question the \type
-%D {*background} mode. This mode is only available when
-%D typesetting the pagebody.
+% maybe use \currentframedhash here
+
+%D For special purposes, users can question the \type {*background} mode. This mode
+%D is only available when typesetting the pagebody.
%D
%D \starttyping
%D \startmode[*background] ...
@@ -42,17 +41,23 @@
\fi
\to \everybeforepagebody
-%D We keep calculations and checks to a minimum and also
-%D try to minimize the amount of tracing due to expansion.
+\unexpanded\def\initializepagebackgrounds
+ {\setfalse\c_page_backgrounds_new
+ \setfalse\c_page_backgrounds_new_right
+ \setfalse\c_page_backgrounds_new_left
+ \setfalse\c_page_backgrounds_some}
+
+%D We keep calculations and checks to a minimum and also try to minimize
+%D the amount of tracing due to expansion.
\let\currentotrbackground\empty
-\def\page_backgrounds_set_yes{\expandafter\let\csname\currentotrbackground\endcsname\relax }
-\def\page_backgrounds_set_nop{\expandafter\let\csname\currentotrbackground\endcsname\undefined}
+%D This is the only spot where we hav ea low level dependency on the way
+%D parent chains are defined but we want the speed.
\def\page_backgrounds_check_background
- {\ifcsname\currentotrbackground\c!background\endcsname
- \edef\page_background_temp{\csname\currentotrbackground\c!background\endcsname}%
+ {\ifcsname\??framed\currentotrbackground:\c!background\endcsname
+ \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}%
\ifx\page_background_temp\empty
\expandafter\expandafter\expandafter\page_backgrounds_check_frame
\else
@@ -63,8 +68,8 @@
\fi}
\def\page_backgrounds_check_frame
- {\ifcsname\currentotrbackground\c!frame\endcsname
- \edef\page_background_temp{\csname\currentotrbackground\c!frame\endcsname}%
+ {\ifcsname\??framed\currentotrbackground:\c!frame\endcsname
+ \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!frame\endcsname}%
\ifx\page_background_temp\v!on
\page_backgrounds_set_yes
\else
@@ -75,8 +80,8 @@
\fi}
\def\page_backgrounds_check_leftframe
- {\ifcsname\currentotrbackground\c!leftframe\endcsname
- \edef\page_background_temp{\csname\currentotrbackground\c!leftframe\endcsname}%
+ {\ifcsname\??framed\currentotrbackground:\c!leftframe\endcsname
+ \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!leftframe\endcsname}%
\ifx\page_background_temp\v!on
\page_backgrounds_set_yes
\else
@@ -87,8 +92,8 @@
\fi}
\def\page_backgrounds_check_rightframe
- {\ifcsname\currentotrbackground\c!rightframe\endcsname
- \edef\page_background_temp{\csname\currentotrbackground\c!rightframe\endcsname}%
+ {\ifcsname\??framed\currentotrbackground:\c!rightframe\endcsname
+ \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!rightframe\endcsname}%
\ifx\page_background_temp\v!on
\page_backgrounds_set_yes
\else
@@ -99,8 +104,8 @@
\fi}
\def\page_backgrounds_check_topframe
- {\ifcsname\currentotrbackground\c!topframe\endcsname
- \edef\page_background_temp{\csname\currentotrbackground\c!topframe\endcsname}%
+ {\ifcsname\??framed\currentotrbackground:\c!topframe\endcsname
+ \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!topframe\endcsname}%
\ifx\page_background_temp\v!on
\page_backgrounds_set_yes
\else
@@ -111,8 +116,8 @@
\fi}
\def\page_backgrounds_check_bottomframe
- {\ifcsname\currentotrbackground\c!bottomframe\endcsname
- \edef\page_background_temp{\csname\currentotrbackground\c!bottomframe\endcsname}%
+ {\ifcsname\??framed\currentotrbackground:\c!bottomframe\endcsname
+ \edef\page_background_temp{\csname\??framed\currentotrbackground:\c!bottomframe\endcsname}%
\ifx\page_background_temp\v!on
\page_backgrounds_set_yes
\else
@@ -122,58 +127,66 @@
\page_backgrounds_set_nop
\fi}
-\def\page_backgrounds_check#1%
- {\edef\currentotrbackground{\??ma#1}%
- \page_backgrounds_check_background}
+%D We don't use the commandhandler code as we want these multitude of backgrounds to be
+%D as fast as possible.
-\def\ifsomebackgroundfound#1%
- {\ifcsname\??ma#1\endcsname}
+\installcorenamespace{layoutbackgrounds}
+\installcorenamespace{layoutbackgroundcheck} % we need another hash as \??layoutbackgrounds<...> gets defined
+
+\def\page_backgrounds_set_yes{\expandafter\let\csname\currentotrbackground\endcsname\relax }
+\def\page_backgrounds_set_nop{\expandafter\let\csname\currentotrbackground\endcsname\undefined}
+
+\unexpanded\def\page_backgrounds_check#1%
+ {\edef\currentotrbackground{\??layoutbackgrounds#1}%
+ \page_backgrounds_check_background}
\def\doifsomebackgroundelse#1%
- {\ifcsname\??ma#1\endcsname
+ {\ifcsname\??layoutbackgrounds#1\endcsname
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
\def\doifsomebackground#1%
- {\ifcsname\??ma#1\endcsname
+ {\ifcsname\??layoutbackgrounds#1\endcsname
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-%D The background mechanism falls back on the \type {\framed}
-%D macro. This means that all normal frame and overlay
-%D features can be used.
+%D The background mechanism falls back on the \type {\framed} macro. This means
+%D that all normal frame and overlay features can be used.
\def\page_backgrounds_add_to_box#1% area
- {\ifcsname\??ma#1\endcsname
+ {\ifcsname\??layoutbackgrounds#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)
+%D We don't need the dimensions here as this is a real framed but the question is:
+%D do we indeed need a real framed or can we use a fake (i.e. no foreground, only
+%D for hidden).
\def\page_backgrounds_add_to_box_indeed#1#2#3#4% area box width height / always non zero
- {\ifcsname\??ma#1\c!setups\endcsname % to be done
- \doprocesslocalsetups{\csname\??ma#1\c!setups\endcsname}% should not produce funny spaces !
+ {\edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1}\c!setups}%
+ \ifx\p_page_backgrounds_setups\empty \else
+ \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces !
\fi
% #2 has the right dimensions already
- \setbox#2\hbox{\localbackgroundframed{\??ma#1}#1#2}}% a real framed (including foreground)
+ \setbox#2\hbox{\localbackgroundframed{\??layoutbackgrounds#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.
+%D There are quite some backgrounds. At the bottom layer, there is the {\em
+%D paper} background. This one is only used for special purposes, like
+%D annotations to documents.
\def\page_backgrounds_add_to_print#1%
{\page_backgrounds_add_to_box\v!paper#1\printpaperwidth\printpaperheight}
-%D The page backgrounds can be put behind the {\em left
-%D page}, the {\em right page} or {\em each page}. As with
-%D the paper background, these are calculated on each page.
+%D The page backgrounds can be put behind the {\em left page}, the {\em
+%D right page} or {\em each page}. As with the paper background, these are
+%D calculated on each page.
\def\page_backgrounds_add_to_paper#1%
{\doifbothsidesoverruled
@@ -182,18 +195,17 @@
{\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,
-%D left margin, text, right margin, right edge}. These are
-%D only recalculated when they change or when the \type
-%D {status} is set to \type {repeat}.
+%D Then there are the 25 areas that make up the layout: {\em top, header, text,
+%D footer, bottom} times {\em left edge, left margin, text, right margin, right
+%D edge}. These are only recalculated when they change or when the \type {status}
+%D is set to \type {repeat}.
\newbox\leftbackground % todo: rename
\newbox\rightbackground % todo: rename
-%D Finaly there is an aditional {\em text} background, again
-%D useful for special purposes only. This one is calculated
-%D each time. The hidden backgrounds are not meant for users!
+%D Finaly there is an aditional {\em text} background, again useful for
+%D special purposes only. This one is calculated each time. The hidden
+%D backgrounds are not meant for users!
\newconditional\c_page_backgrounds_hidden_enabled
@@ -203,21 +215,19 @@
\fi
\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
-%D and depth of the page are used for alignment purposes.
+%D The next couple of macros implement the area backgrounds. As said, these
+%D are cached in dedicated boxes. The offsets and depth of the page are used
+%D for alignment purposes.
-\newdimen\pageoffset % bleed
-\newdimen\pagedepth
+%newdimen\pageoffset % bleed
+%newdimen\pagedepth % built-in
-%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.
+%D We need a bit more clever mechanism in order to handle layers well.
+%D This means that we cannot calculate both background at the same time
+%D since something may have changed halfway a page.
-%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.
+%D Margin swapping has been simplified: see mkii code in case of regression.
+%D Calculation is delayed till the page anyway so the state is known.
\def\page_backgrounds_recalculate
{\global\settrue\c_page_backgrounds_new}
@@ -230,7 +240,7 @@
\page_backgrounds_set_boxes_a
\page_backgrounds_set_boxes_b
\page_backgrounds_set_boxes_c
- \ifx\@@mastate\v!repeat\else
+ \ifx\p_page_backgrounds_state\v!repeat\else
\global\setfalse\c_page_backgrounds_new
\fi}
@@ -273,20 +283,19 @@
\newdimen\pagebackgroundhoffset % THESE WILL BECOME OBSOLETE
\newdimen\pagebackgroundvoffset
+\newdimen\pagebackgroundoffset % used elsewhere
\newdimen\pagebackgrounddepth
\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}
\def\page_backgrounds_set_offsets_indeed
- {\ifcsname\??ma\v!text\v!text\endcsname
+ {\ifcsname\??layoutbackgrounds\v!text\v!text\endcsname
\page_backgrounds_set_offsets_yes
- \else\ifcsname\??ma\v!text\endcsname
+ \else\ifcsname\??layoutbackgrounds\v!text\endcsname
\page_backgrounds_set_offsets_yes
\else
\page_backgrounds_set_offsets_nop
@@ -299,26 +308,27 @@
\global\pagebackgroundcompensation\zeropoint}
\def\page_backgrounds_set_offsets_yes
- {\global\pagebackgroundcompensation\csname\??ma\v!page\c!offset\endcsname\relax
+ {\global\pagebackgroundoffset \d_page_backgrounds_depth
+ \global\pagebackgroundcompensation\d_page_backgrounds_offset\relax
\ifzeropt\pagebackgroundcompensation
\page_backgrounds_set_offsets_nop
\else
- \ifcsname\??ma\v!top\v!text\endcsname
+ \ifcsname\??layoutbackgrounds\v!top\v!text\endcsname
\global\pagebackgroundhoffset\zeropoint
- \else\ifcsname\??ma\v!bottom\v!text\endcsname
+ \else\ifcsname\??layoutbackgrounds\v!bottom\v!text\endcsname
\global\pagebackgroundhoffset\zeropoint
\else
\global\pagebackgroundhoffset\pagebackgroundcompensation
\fi\fi
- \ifcsname\??ma\v!text\v!rightedge\endcsname
+ \ifcsname\??layoutbackgrounds\v!text\v!rightedge\endcsname
\global\pagebackgroundvoffset\zeropoint
\global\pagebackgrounddepth \zeropoint
- \else\ifcsname\??ma\v!text\v!leftedge\endcsname
+ \else\ifcsname\??layoutbackgrounds\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
+ \global\pagebackgrounddepth \d_page_backgrounds_depth
\fi\fi
\fi}
@@ -370,7 +380,7 @@
\bgroup\hbox\bgroup
\goleftonpage
\ifdim\leftedgewidth>\zeropoint
- \ifcsname\??ma#1\v!leftedge\endcsname
+ \ifcsname\??layoutbackgrounds#1\v!leftedge\endcsname
\page_backgrounds_set_box_cell#1\v!leftedge\leftedgewidth#2%
\else
\kern\leftedgewidth
@@ -378,21 +388,21 @@
\kern\leftedgedistance
\fi
\ifdim\leftmarginwidth>\zeropoint
- \ifcsname\??ma#1\v!leftmargin\endcsname
+ \ifcsname\??layoutbackgrounds#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
+ \ifcsname\??layoutbackgrounds#1\v!text\endcsname
\page_backgrounds_set_box_cell#1\v!text\makeupwidth#2%
\else
\kern\makeupwidth
\fi
\ifdim\rightmarginwidth>\zeropoint
\kern\rightmargindistance
- \ifcsname\??ma#1\v!rightmargin\endcsname
+ \ifcsname\??layoutbackgrounds#1\v!rightmargin\endcsname
\page_backgrounds_set_box_cell#1\v!rightmargin\rightmarginwidth#2%
\else
\kern\rightmarginwidth
@@ -400,7 +410,7 @@
\fi
\ifdim\rightedgewidth>\zeropoint
\kern\rightedgedistance
- \ifcsname\??ma#1\v!rightedge\endcsname
+ \ifcsname\??layoutbackgrounds#1\v!rightedge\endcsname
\page_backgrounds_set_box_cell#1\v!rightedge\rightedgewidth#2%
\else
\kern\rightedgewidth
@@ -415,30 +425,31 @@
\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 !
+ \edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1#2}\c!setups}%
+ \ifx\p_page_backgrounds_setups\empty \else
+ \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces !
\fi
- \ifcsname\??ma#1#2\c!command\endcsname
+ \edef\p_page_backgrounds_command{\namedframedparameter{\??layoutbackgrounds#1#2}\c!command}%
+ \ifx\p_page_backgrounds_command\empty
\expandafter\page_backgrounds_set_box_cell_nop
\else
\expandafter\page_backgrounds_set_box_cell_yes
- \fi#1#2#3#4%
- \localbackgroundframed{\??ma#1#2}{#1:#2}\scratchbox
+ \fi#3#4%
+ \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}\scratchbox
\endgroup}
-\def\page_backgrounds_set_box_cell_nop#1#2#3#4%
+\def\page_backgrounds_set_box_cell_nop#1#2%
{\setbox\scratchbox\emptyvbox
- \wd\scratchbox#3%
- \ht\scratchbox#4}
+ \wd\scratchbox#1%
+ \ht\scratchbox#2}
-\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}%
+\def\page_backgrounds_set_box_cell_yes#1#2%
+ {\setbox\scratchbox\vbox to #2{\vss\hbox to#1{\hss\p_page_backgrounds_command\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
-%D usage, but since today's \TEX's are large, we now do the
-%D work on forehand.
+%D The background mechanism is quite demanding in terms or resources. We used to
+%D delay these definitions till runtime usage, but since today's \TEX's are large,
+%D we now do the work on forehand.
%D
%D \starttyping
%D \setupbackgrounds [settings]
@@ -448,110 +459,115 @@
%D
%D \showsetup{setupbackgrounds}
%D
-%D Because the number of arguments runs from one to three,
-%D we need to check for it.
+%D Because the number of arguments runs from one to three, we need to check
+%D for it.
\newtoks\everybackgroundssetup
\unexpanded\def\setupbackgrounds
{\dotripleempty\page_backgrounds_setup}
-\def\page_backgrounds_setup[#1][#2][#3]%
+\def\page_backgrounds_setup
{\ifthirdargument
- \page_backgrounds_setup_double{#1}{#2}{#3}%
+ \expandafter\page_backgrounds_setup_double
\else\ifsecondargument
- \page_backgrounds_setup_single{#1}{#2}%
+ \doubleexpandafter\page_backgrounds_setup_single
\else\iffirstargument
- \page_backgrounds_setup_basics{#1}%
- \fi\fi\fi
- \the\everybackgroundssetup}
+ \tripleexpandafter\page_backgrounds_setup_basics
+ \fi\fi\fi}
+
+\newdimen\d_page_backgrounds_offset
+\newdimen\d_page_backgrounds_depth
\appendtoks
- \doifelsevalue{\??ma\v!page\c!offset}\v!overlay
- {\global\pageoffset\zeropoint}
- {\global\pageoffset\csname\??ma\v!page\c!offset\endcsname}%
- \global\pagedepth\csname\??ma\v!page\c!depth\endcsname
- \global\pagebackgroundoffset\pageoffset
- \global\pagebackgrounddepth\pagedepth
- \doifelse\@@mastate\v!stop
- {\global\setfalse\c_page_backgrounds_new}
- {\global\settrue \c_page_backgrounds_new}%
+ \edef\p_page_backgrounds_offset{\namedframedparameter{\??layoutbackgrounds\v!page}\c!offset}%
+ \edef\p_page_backgrounds_depth {\namedframedparameter{\??layoutbackgrounds\v!page}\c!depth }%
+ \edef\p_page_backgrounds_state {\namedframedparameter{\??layoutbackgrounds }\c!state }%
+ \global\d_page_backgrounds_offset\ifx\p_offset\empty\zeropoint\else\p_page_backgrounds_offset\fi
+ \global\d_page_backgrounds_depth \ifx\p_depth \empty\zeropoint\else\p_page_backgrounds_depth \fi
+ \global\pagebackgroundoffset\d_page_backgrounds_offset\relax
+ \global\pagebackgrounddepth \d_page_backgrounds_depth \relax
+ \ifx\p_page_backgrounds_state\v!stop
+ \global\setfalse\c_page_backgrounds_new
+ \else
+ \global\settrue \c_page_backgrounds_new
+ \fi
\to \everybackgroundssetup
\def\v_page_backgrounds_double_set{\v!paper,\v!page,\v!leftpage,\v!rightpage}
\def\v_page_backgrounds_single_set{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage}
\def\v_page_backgrounds_common_set{\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge}
-\def\page_backgrounds_setup_double#1#2#3%
+\def\page_backgrounds_setup_double[#1][#2][#3]% if needed we can speed this up
{\global\settrue\c_page_backgrounds_some
- \def\docommand##1%
+ \def\page_backgrounds_setup_step##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_step_nested####1{\page_backgrounds_setup_and_check{##1####1}{#3}}%
+ \processcommalist[#2]\page_backgrounds_setup_step_nested}}%
+ \processcommalist[#1]\page_backgrounds_setup_step
+ \the\everybackgroundssetup}
-\def\page_backgrounds_setup_single#1#2%
+\def\page_backgrounds_setup_single[#1][#2][#3]%
{\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_step##1{\page_backgrounds_setup_and_check{##1}{#2}}%
+ \processcommalist[#1]\page_backgrounds_setup_step
+ \the\everybackgroundssetup}%
+ {\page_backgrounds_setup_double[#1][\v_page_backgrounds_common_set][#2]}}
-\def\page_backgrounds_setup_basics#1%
- {\getparameters[\??ma][#1]}
+\def\page_backgrounds_setup_basics[#1][#2][#3]%
+ {\setupframed[\??layoutbackgrounds][#1]%
+ \the\everybackgroundssetup}
\def\page_backgrounds_setup_and_check#1#2% tag settings
- {\edef\currentotrbackground{\??ma#1}%
- \getparameters[\currentotrbackground][#2]%
+ {\edef\currentotrbackground{\??layoutbackgrounds#1}%
+ \setupframed[\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.
-
-% hm, we can delay them
+%D Each areas (currently there are $1+3+25+1=30$ of them) has its own low level
+%D framed object associated.
+
+\definesimplifiedframed[\??layoutbackgrounds\v!paper]
+\definesimplifiedframed[\??layoutbackgrounds\v!page]
+\definesimplifiedframed[\??layoutbackgrounds\v!leftpage]
+\definesimplifiedframed[\??layoutbackgrounds\v!rightpage]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!hidden]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightedge]
+
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftedge]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!text]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightmargin]
+\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightedge]
-\unexpanded\def\installsomebackground#1#2{\inheritlocalframed[\??ma#1#2][\??od]}
-
-\installsomebackground \v!paper \empty
-\installsomebackground \v!page \empty
-\installsomebackground \v!leftpage \empty
-\installsomebackground \v!rightpage \empty
-
-%D The stand alone text area inherits from the page too.
-
-\installsomebackground \v!text \empty
-\installsomebackground \v!hidden \empty
-
-%D We save some keying by defining the areas using a helper:
-
-\def\docommand#1%
- {\installsomebackground#1\v!leftedge
- \installsomebackground#1\v!leftmargin
- \installsomebackground#1\v!text
- \installsomebackground#1\v!rightmargin
- \installsomebackground#1\v!rightedge}
-
-\docommand \v!top
-\docommand \v!header
-\docommand \v!text
-\docommand \v!footer
-\docommand \v!bottom
-
-%D We need some cleanup now.
-
-\let\docommand\relax
-
-%D We now set up the individual areas to use reasonable
-%D defaults.
-
-\installsomebackground \v!paper \empty
-\installsomebackground \v!page \empty
-\installsomebackground \v!leftpage \empty
-\installsomebackground \v!rightpage \empty
-
-\getparameters
- [\??ma\v!page]
+\setupbackgrounds
+ [\v!page]
[\c!offset=\zeropoint, % hm, so we need to force overlay elsewhere
\c!depth=\zeropoint]
@@ -560,29 +576,23 @@
\setupbackgrounds
[\c!state=\c!start]
-%D The hidden layer can be populated by extending the
-%D following comma separated list. This only happens in core
-%D modules.
+%D The hidden layer can be populated by extending the following comma separated
+%D list. This only happens in core modules.
% todo page-2 .. page+2 achter pagina -> bleed
% spread-2 .. spread+2 achter spread -> spread (repeat 2 times)
-\def\enablehiddenbackground
+\unexpanded\def\enablehiddenbackground
{\global\settrue\c_page_backgrounds_hidden_enabled
\global\settrue\c_page_backgrounds_some
\page_backgrounds_recalculate}
-\def\disablehiddenbackground
+\unexpanded\def\disablehiddenbackground
{\global\setfalse\c_page_backgrounds_hidden_enabled}
\def\hiddenbackgroundlist
{\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2}
-% \defineoverlay[\v!text-2][\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}]
@@ -592,13 +602,19 @@
[\v!hidden]
[\c!background=\hiddenbackgroundlist]
-% The next series is used in local (for instance floating)
-% backgrounds.
+%D Because we haven't really set up backgrounds yet, we set the main efficiency
+%D switch to false.
+
+\setfalse\c_page_backgrounds_some
+
+\protect \endinput
-% \installsomebackground \v!local \empty % not really a background, invisible for users
+% %D The next series is used in local (for instance floating) backgrounds.
+%
+% \installsimplifiedframed{\??layoutbackgrounds\v!local}
%
% \getparameters
-% [\??ma\v!local]
+% [\??layoutbackgrounds\v!local]
% [\c!component=local,
% \c!background=\localbackgroundlist]
%
@@ -618,7 +634,7 @@
% \fi}
%
% \def\page_backgrounds_add_local_to_box_indeed#1%
-% {\setbox#1\hbox{\localbackgroundframed{\??ma\v!local}\v!local#1}%
+% {\setbox#1\hbox{\localbackgroundframed{\??layoutbackgrounds\v!local}\v!local#1}%
% \global\advance\localpositionnumber\plusone} % afterwards !
%
% \let\page_backgrounds_add_local_to_box\gobbleoneargument
@@ -633,9 +649,3 @@
% \input tufte
% \stopcolumnset
-%D Because we haven't really set up backgrounds yet, we set
-%D the main efficiency switch to false.
-
-\setfalse\c_page_backgrounds_some
-
-\protect \endinput
diff --git a/tex/context/base/page-brk.mkiv b/tex/context/base/page-brk.mkiv
index 722556760..ac1fffd6b 100644
--- a/tex/context/base/page-brk.mkiv
+++ b/tex/context/base/page-brk.mkiv
@@ -53,9 +53,9 @@
\def\page_breaks_handle#1%
{\edef\page_breaks_current_options{#1}% handy for tracing
- \processcommacommand[\page_breaks_current_options]\page_breaks_handle_indeed}
+ \processcommacommand[\page_breaks_current_options]\page_breaks_handle_step}
-\def\page_breaks_handle_indeed#1%
+\def\page_breaks_handle_step#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
@@ -80,7 +80,8 @@
{\setvalue{\??pagebreaks#1}{#2}}
\unexpanded\def\pagebreak
- {\dosingleempty\page_breaks_process}
+ {\par % else no vertical penalties
+ \dosingleempty\page_breaks_process}
\let\page\pagebreak
@@ -269,9 +270,9 @@
\def\page_breaks_columns_handle#1%
{\edef\page_breaks_columns_current_options{#1}%
- \processcommacommand[#1]\page_breaks_columns_handle_indeed}
+ \processcommacommand[#1]\page_breaks_columns_handle_step}
-\def\page_breaks_columns_handle_indeed#1%
+\def\page_breaks_columns_handle_step#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
@@ -296,7 +297,8 @@
{\setvalue{\??columnbreaks#1}{#2}}
\unexpanded\def\columnbreak
- {\dosingleempty\page_breaks_columns_process}
+ {\par % else no vertical penalties
+ \dosingleempty\page_breaks_columns_process}
\let\column\columnbreak
diff --git a/tex/context/base/page-col.mkiv b/tex/context/base/page-col.mkiv
index 50a05d351..14b512421 100644
--- a/tex/context/base/page-col.mkiv
+++ b/tex/context/base/page-col.mkiv
@@ -13,74 +13,36 @@
\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.
+%D Here we implement a couple of helpers for dealing with columns. For
+%D the moment we keep the names. When the mul and set modules are redone
+%D these can be adapted or disappear.
\unprotect
-%D The next two registers can be used to store pre column
-%D material as well as footnotes or so.
+%D We reserve a counter for the number of columns as well as the current
+%D column. Both are not to be changed by users!
-\newbox\precolumnbox \newdimen\precolumnboxheight
-\newbox\postcolumnbox \newdimen\postcolumnboxheight
+\newcount\nofcolumns \nofcolumns\plusone
+\newcount\mofcolumns \mofcolumns\plusone
-%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
+\newconstant\columndirection % 0:lr 1:rl
\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 During initialization the temporary boxes are allocated. This enables us to
+%D use as much columns as we want, without exhausting the pool of boxes too
+%D fast. We could have packed 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.
+%D Two sets of boxes are declared, the txtboxes are used for the text, the
+%D topboxes are for moved column floats.
+
+\installcorenamespace{columntext}
+\installcorenamespace{columnfooter}
+\installcorenamespace{columntop}
+\installcorenamespace{columnbottom}
-\def\initializecolumns#1%
+\unexpanded\def\initializecolumns#1%
{\ifnum#1>\maxnofcolumns
\showmessage\m!columns1\maxnofcolumns
\nofcolumns\maxnofcolumns
@@ -88,17 +50,23 @@
\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
+ \page_columns_allocate
\fi}
+\def\page_columns_allocate
+ {\dorecurse\nofcolumns
+ {\ifnum\recurselevel>\allocatednofcolumns\relax
+ \ifcsname\??columntext\recurselevel\endcsname \else
+ \expandafter\newbox\csname\??columntext \recurselevel\endcsname % text
+ \expandafter\newbox\csname\??columnfooter\recurselevel\endcsname % footer
+ \expandafter\newbox\csname\??columntop \recurselevel\endcsname % top insert
+ \expandafter\newbox\csname\??columnbottom\recurselevel\endcsname % bottom insert
+ \fi
+ \fi}%
+ \global\allocatednofcolumns\nofcolumns}
+
+\def\currentcolumn {1}
+
\def\firstcolumnbox {\columntextbox\plusone}
\def\currentcolumnbox {\columntextbox\mofcolumns}
\def\lastcolumnbox {\columntextbox\nofcolumns}
@@ -107,50 +75,105 @@
\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}}
+\def\columntextbox #1{\csname\??columntext \number#1\endcsname}
+\def\columnfootbox #1{\csname\??columnfooter\number#1\endcsname}
+\def\columntopbox #1{\csname\??columntop \number#1\endcsname}
+\def\columnbotbox #1{\csname\??columnbottom\number#1\endcsname}
+
+\unexpanded\def\columnsettextbox {\global\setbox\columntextbox}
+\unexpanded\def\columnsetfootbox {\global\setbox\columnfootbox}
+\unexpanded\def\columnsettopbox {\global\setbox\columntopbox}
+\unexpanded\def\columnsetbotbox {\global\setbox\columnbotbox}
+
+\unexpanded\def\columngettextbox {\copy\columntextbox}
+\unexpanded\def\columngetfootbox {\copy\columnfootbox}
+\unexpanded\def\columngettopbox {\copy\columntopbox}
+\unexpanded\def\columngetbotbox {\copy\columnbotbox}
+
+\unexpanded\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}}
+\unexpanded\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}}
+\unexpanded\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}}
+\unexpanded\def\columnerasebotboxes {\dorecurse\allocatednofcolumns{\columnsetbotbox \recurselevel\emptybox}}
+
+%D Without going in details we present two macro's which handle the columns. The
+%D action which is transfered by the the first and only parameter can do something
+%D with \type {\currentcolumnbox}. In case of the mid columns, \type
+%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled outside these macro's.
+
+% \unexpanded\def\dohandlecolumn#1%
+% {\mofcolumns\recurselevel
+% \let\currentcolumn\recurselevel
+% #1\relax}
+%
+% \unexpanded\def\dohandleallcolumns#1%
+% {\dorecurse\nofcolumns{\dohandlecolumn{#1}}}
+%
+% \unexpanded\def\dohandlerevcolumns#1%
+% {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}}
+%
+% \unexpanded\def\dohandlemidcolumns#1%
+% {\dohandleallcolumns
+% {\ifnum\recurselevel>\plusone
+% \ifnum\recurselevel<\nofcolumns
+% \dohandlecolumn{#1}%
+% \fi
+% \fi}}
+%
+% As we don't nest we can use a fast variant:
+
+\unexpanded\def\dohandleallcolumnscs#1{\let\page_columns_action #1\page_columns_all_indeed}
+\unexpanded\def\dohandleallcolumns #1{\def\page_columns_action{#1}\page_columns_all_indeed}
+
+\unexpanded\def\dohandlerevcolumnscs#1{\let\page_columns_action #1\page_columns_rev_indeed}
+\unexpanded\def\dohandlerevcolumns #1{\def\page_columns_action{#1}\page_columns_rev_indeed}
+
+\unexpanded\def\dohandlemidcolumnscs#1{\let\page_columns_action #1\page_columns_mid_indeed}
+\unexpanded\def\dohandlemidcolumns #1{\def\page_columns_action{#1}\page_columns_mid_indeed}
+
+\unexpanded\def\page_columns_all_indeed
+ {\mofcolumns\plusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_all_next
+ \fi}
+
+\unexpanded\def\page_columns_all_next
+ {\advance\mofcolumns\plusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_all_next
+ \fi}
+
+\unexpanded\def\page_columns_rev_indeed
+ {\mofcolumns\nofcolumns
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns>\plusone
+ \expandafter\page_columns_rev_prev
+ \fi}
+
+\unexpanded\def\page_columns_rev_prev
+ {\advance\mofcolumns\minusone
+ \edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \ifnum\mofcolumns>\plusone
+ \expandafter\page_columns_rev_prev
+ \fi}
+
+\unexpanded\def\page_columns_mid_indeed
+ {\mofcolumns\plustwo
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_mid_next
+ \fi}
+
+\unexpanded\def\page_columns_mid_next
+ {\edef\currentcolumn{\the\mofcolumns}%
+ \page_columns_action\relax
+ \advance\mofcolumns\plusone
+ \ifnum\mofcolumns<\nofcolumns
+ \expandafter\page_columns_mid_next
+ \fi}
\protect \endinput
diff --git a/tex/context/base/page-com.mkiv b/tex/context/base/page-com.mkiv
index 80012dd14..61cb49e89 100644
--- a/tex/context/base/page-com.mkiv
+++ b/tex/context/base/page-com.mkiv
@@ -30,79 +30,141 @@
%D \stoppagecomment
%D \stoptyping
-\unexpanded\def\setuppagecomment
- {\dosingleempty\dosetuppagecomment}
-
-\def\dosetuppagecomment[#1]%
- {\getparameters[\??pc][#1]%
- \doifelse\@@pcstate\v!start
- {\doifinsetelse\@@pclocation{\v!bottom,\v!top}
- {\setuppapersize[\c!left=\hskip\@@pcoffset]%
- \edef\@@pcpaperheight{\the\dimexpr\paperheight+\@@pcoffset+\@@pcoffset+\@@pcdistance+\@@pcheight}%
- \edef\@@pcpaperwidth {\the\dimexpr\paperwidth +\@@pcoffset+\@@pcoffset}%
- \defineoverlay[\v!pagecomment][\placepagecommentTB]}
- {\setuppapersize[\c!top=\vskip\@@pcoffset]%
- \edef\@@pcpaperheight{\the\dimexpr\paperheight+\@@pcoffset+\@@pcoffset}%
- \edef\@@pcpaperwidth {\the\dimexpr\paperwidth +\@@pcoffset+\@@pcoffset+\@@pcdistance+\@@pcwidth}%
- \defineoverlay[\v!pagecomment][\placepagecommentLR]}%
- \processaction
- [\@@pclocation]
- [ \v!bottom=>{\setuplayout[\c!location=]\setuppapersize[\c!bottom=\vss,\c!top =\vskip\@@pcoffset]},
- \v!top=>{\setuplayout[\c!location=]\setuppapersize[\c!top =\vss,\c!bottom=\vskip\@@pcoffset]},
- \v!left=>{\setuplayout[\c!location=]\setuppapersize[\c!left =\hss,\c!right =\hskip\@@pcoffset]},
- \v!right=>{\setuplayout[\c!location=]\setuppapersize[\c!right =\hss,\c!left =\hskip\@@pcoffset]}]%
- \definepapersize
- [\v!pagecomment]
- [\c!height=\@@pcpaperheight,
- \c!width=\@@pcpaperwidth]%
- \let\@@pcprintpapersize\printpapersize
- \setuppapersize[\papersize][\v!pagecomment]%
- \setupbackgrounds[\v!paper][\c!background=\v!pagecomment]}% todo append if already set
- {\doif\@@pcstate\v!stop % else initialization invokes backgrounds
- {% this should be tested first
- % \normalexpanded{\noexpand\setuppapersize[\papersize][\@@pcprintpapersize]}%
- \setupbackgrounds[\v!paper][\c!background=]}}}
-
-\def\@@pcprintpapersize{\printpapersize}
-
-\unexpanded\def\placepagecommentTB
+\installcorenamespace{pagecomment}
+\installcorenamespace{pagecommentlocations}
+\installcorenamespace{pagecommentstates}
+
+\newdimen\d_page_comments_offset
+\newdimen\d_page_comments_page_width
+\newdimen\d_page_comments_page_height
+\newdimen\d_page_comments_width
+\newdimen\d_page_comments_height
+\newdimen\d_page_comments_distance
+
+\newconditional\c_page_comment_enabled
+
+\let\p_page_commands_location\v!none
+\let\p_page_commands_state \v!stop
+
+\installsetuponlycommandhandler \??pagecomment {pagecomment}
+
+\appendtoks
+ \edef\p_page_commands_location{\directpagecommentparameter\c!location}%
+ \edef\p_page_commands_state {\directpagecommentparameter\c!state}%
+ \expandcheckedcsname\??pagecommentstates\p_page_commands_state\v!none
+\to \everysetuppagecomment
+
+\ifdefined\scrn_canvas_synchronize_simple
+
+ \appendtoks
+ \ifx\p_page_commands_state\v!start
+ \scrn_canvas_synchronize_simple
+ \else
+ \scrn_canvas_synchronize_complex
+ \fi
+ \to \everyshipout
+
+\fi
+
+\setvalue{\??pagecommentstates\v!start}%
+ {\d_page_comments_offset \directpagecommentparameter\c!offset \relax
+ \d_page_comments_distance\directpagecommentparameter\c!distance\relax
+ \d_page_comments_width \directpagecommentparameter\c!width \relax
+ \d_page_comments_height \directpagecommentparameter\c!height \relax
+ \expandcheckedcsname\??pagecommentlocations\p_page_commands_location\v!none
+ \definepapersize[\v!pagecomment][\c!height=\d_page_comments_page_height,\c!width=\d_page_comments_page_width]%
+ \setuppapersize[\papersize][\v!pagecomment]%
+ \setupbackgrounds[\v!paper][\c!background=\v!pagecomment]} % maybe append if already set
+
+\setvalue{\??pagecommentstates\v!stop}%
+ {\setupbackgrounds[\v!paper][\c!background=]}
+
+\setvalue{\??pagecommentstates\v!none}%
+ {}
+
+\setvalue{\??pagecommentlocations\v!bottom}%
+ {\setuplayout[\c!location=]%
+ \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=\vss,\c!left=\hskip\d_page_comments_offset,\c!right=]%
+ \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_height\relax
+ \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset\relax
+ \defineoverlay[\v!pagecomment][\page_comments_top_bottom]}
+
+\setvalue{\??pagecommentlocations\v!top}%
+ {\setuplayout[\c!location=]%
+ \setuppapersize[\c!top=\vss,\c!bottom=\vskip\d_page_comments_offset,\c!left=\hskip\d_page_comments_offset,\c!right=]%
+ \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_height\relax
+ \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset\relax
+ \defineoverlay[\v!pagecomment][\page_comments_top_bottom]}
+
+\setvalue{\??pagecommentlocations\v!left}%
+ {\setuplayout[\c!location=]%
+ \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=,\c!left=\hss,\c!right=\hskip\d_page_comments_offset]%
+ \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset\relax
+ \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_width\relax
+ \defineoverlay[\v!pagecomment][\page_comments_left_right]}
+
+\setvalue{\??pagecommentlocations\v!right}%
+ {\setuplayout[\c!location=]%
+ \setuppapersize[\c!top=\vskip\d_page_comments_offset,\c!bottom=,\c!left=\hskip\d_page_comments_offset,\c!right =\hss]%
+ \d_page_comments_page_height\dimexpr\paperheight+2\d_page_comments_offset\relax
+ \d_page_comments_page_width \dimexpr\paperwidth +2\d_page_comments_offset+\d_page_comments_distance+\d_page_comments_width\relax
+ \defineoverlay[\v!pagecomment][\page_comments_left_right]}
+
+\setvalue{\??pagecommentlocations\v!none}%
+ {}% \setuppapersize[\c!bottom=,\c!top=,\c!left=,\c!right=]}
+
+\unexpanded\def\page_comments_top_bottom
{\vbox to \printpaperheight
{%\forgetall
- \hsize\printpaperwidth
- \vskip\@@pcoffset
- \doifelse\@@pclocation\v!bottom{\vskip\dimexpr\paperheight+\@@pcdistance\relax}\vss
- \hskip\@@pcoffset
- \vbox to \@@pcheight
+ \hsize\printpaperwidth\relax
+ \ifx\p_page_commands_location\v!bottom
+ \vskip\dimexpr\paperheight+\d_page_comments_distance+\d_page_comments_offset\relax
+ \else
+ \vskip\d_page_comments_offset
+ \vss
+ \fi
+ \hskip\d_page_comments_offset
+ \vbox to \d_page_comments_height
{%\forgetall
\hsize\paperwidth
- \ifpagecomment
+ \ifconditional\c_page_comment_enabled
\getbuffer[\v!pagecomment]%
- \global\pagecommentfalse
+ \global\setfalse\c_page_comment_enabled
\fi}%
\hfill
- \doifelse\@@pclocation\v!bottom\vss{\vskip\dimexpr\paperheight+\@@pcdistance\relax}%
- \vskip\@@pcoffset}}
+ \ifx\p_page_commands_location\v!bottom
+ \vss
+ \vskip\d_page_comments_offset
+ \else
+ \vskip\dimexpr\paperheight+\d_page_comments_distance+\d_page_comments_offset\relax
+ \fi}}
-\unexpanded\def\placepagecommentLR
+\unexpanded\def\page_comments_left_right
{\hbox to \printpaperwidth
- {\hskip\@@pcoffset
- \doifelse\@@pclocation\v!right{\hskip\paperwidth\hskip\@@pcdistance}\hss
+ {\ifx\p_page_commands_location\v!right
+ \hskip\dimexpr\paperwidth+\d_page_comments_distance+\d_page_comments_offset\relax
+ \else
+ \hskip\d_page_comments_offset
+ \hss
+ \fi
\vbox to \printpaperheight
{%\forgetall
- \vskip\@@pcoffset
- \hsize\@@pcwidth
- \ifpagecomment
+ \vskip\d_page_comments_offset
+ \hsize\d_page_comments_width
+ \ifconditional\c_page_comment_enabled
\getbuffer[\v!pagecomment]%
- \global\pagecommentfalse
+ \global\setfalse\c_page_comment_enabled
\fi
\vss}%
- \doifelse\@@pclocation\v!right\hss{\hskip\paperwidth\hskip\@@pcdistance}%
- \hskip\@@pcoffset}}
-
-\newif\ifpagecomment
+ \ifx\p_page_commands_location\v!right
+ \hss
+ \hskip\d_page_comments_offset
+ \else
+ \hskip\dimexpr\paperwidth+\d_page_comments_distance+\d_page_comments_offset\relax
+ \fi}}
\setvalue{\e!start\v!pagecomment}%
- {\global\pagecommenttrue
+ {\global\settrue\c_page_comment_enabled
\grabbufferdatadirect\v!pagecomment{\e!start\v!pagecomment}{\e!stop\v!pagecomment}}
\setuppagecomment
diff --git a/tex/context/base/page-fac.mkiv b/tex/context/base/page-fac.mkiv
index fef1cd5ac..88789abe9 100644
--- a/tex/context/base/page-fac.mkiv
+++ b/tex/context/base/page-fac.mkiv
@@ -25,19 +25,21 @@
%D \stoptext
%D \stoptyping
-\newbox\b_page_facings_content
+\newbox \b_page_facings_content
+\newconditional\c_page_facings_busy
-\unexpanded\def\setupoppositeplacing
- {\dodoubleargument\getparameters[\??np]}
+\installcorenamespace{oppositeplacing}
+
+\installsetuponlycommandhandler \??oppositeplacing {oppositeplacing}
\unexpanded\def\startopposite
{\dowithnextboxcontent
{\hsize\makeupwidth}%
{\global\setbox\b_page_facings_content\vbox
{\ifvoid\b_page_facings_content
- \@@npbefore
+ \directoppositeplacingparameter\c!before
\else
- \@@npinbetween
+ \directoppositeplacingparameter\c!inbetween
\unvbox\b_page_facings_content
\fi
\box\nextbox}}%
@@ -47,26 +49,34 @@
{\egroup}
\def\page_facings_finish
- {\ifvoid\b_page_facings_content\else
+ {\ifvoid\b_page_facings_content \else
\global\setbox\b_page_facings_content\vbox to \makeupheight
{\unvbox\b_page_facings_content
- \@@npafter
+ \directoppositeplacingparameter\c!after
\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}}
+ {\ifconditional\c_page_facings_busy
+ \ifvoid\b_page_facings_content \else
+ \page_facings_flush_indeed
+ \fi
+ \fi}
+
+\def\page_facings_flush_indeed
+ {\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}
+
+\appendtoks
+ \doifelse{\directoppositeplacingparameter\c!state}\v!start\settrue\setfalse\c_page_facings_busy
+\to \everysetupoppositeplacing
\setupoppositeplacing
[\c!state=\v!start,
diff --git a/tex/context/base/page-flt.lua b/tex/context/base/page-flt.lua
index ecd7004ae..c383380fb 100644
--- a/tex/context/base/page-flt.lua
+++ b/tex/context/base/page-flt.lua
@@ -243,11 +243,10 @@ local label = P(":") * C((1-S(",*: "))^0)
local pattern = method * (
label * position
+ C("") * position
- + label
+ + label * C("") * C("")
+ C("") * C("") * C("")
) + C("") * C("") * C("") * C("")
-
-- inspect { lpegmatch(pattern,"somewhere:blabla,crap") }
-- inspect { lpegmatch(pattern,"somewhere:1*2") }
-- inspect { lpegmatch(pattern,"somewhere:blabla:1*2") }
@@ -262,6 +261,9 @@ end
-- interface
+local context = context
+local setvalue = context.setvalue
+
commands.flushfloat = floats.flush
commands.savefloat = floats.save
commands.resavefloat = floats.resave
@@ -278,8 +280,8 @@ function commands.doifelsesavedfloat(...) commands.doifelse(floats.nofstacked(..
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)
+ setvalue("floatmethod",method)
+ setvalue("floatlabel", label )
+ setvalue("floatrow", row )
+ setvalue("floatcolumn",column)
end
diff --git a/tex/context/base/page-flt.mkiv b/tex/context/base/page-flt.mkiv
index 18c0ad263..65abc844c 100644
--- a/tex/context/base/page-flt.mkiv
+++ b/tex/context/base/page-flt.mkiv
@@ -20,31 +20,42 @@
\unprotect
-%D To be checked and removed
+\ifdefined\s!topfloat \else \def\s!topfloat {topfloat} \fi
+\ifdefined\s!bottomfloat \else \def\s!bottomfloat{bottomfloat} \fi
-%def\dosavefloatinfo {\showmessage\m!floatblocks2{\the\totalnoffloats}}
-\def\doinsertfloatinfo {\showmessage\m!floatblocks4{\the\totalnoffloats}}
-\def\dofloatflushedinfo{\showmessage\m!floatblocks3{\the\numexpr\totalnoffloats-\savednoffloats\relax}}
+\defineinsertion[\s!topfloat]
+\defineinsertion[\s!bottomfloat]
+
+\newdimen \d_page_floats_inserted_bottom
+\newdimen \d_page_floats_inserted_top
+\newcount \c_page_floats_n_of_top \c_page_floats_n_of_top \plustwo
+\newcount \c_page_floats_n_of_bottom \c_page_floats_n_of_bottom\zerocount
+
+\newconstant\c_page_floats_insertions_topskip_mode % 1 = no topskip
+
+%def\page_floats_report_saved {\showmessage\m!floatblocks2{\the\totalnoffloats}}
+\def\page_floats_report_total {\showmessage\m!floatblocks4{\the\totalnoffloats}}
+\def\page_floats_report_flushed{\showmessage\m!floatblocks3{\the\numexpr\totalnoffloats-\savednoffloats\relax}}
%D Extra float registers.
-\newif\ifsomefloatwaiting \somefloatwaitingfalse
-\newif\ifroomforfloat \roomforfloattrue
-\newif\ifnofloatpermitted \nofloatpermittedfalse
-\newif\ifcenterfloatbox \centerfloatboxtrue
-\newif\iflocalcenterfloatbox \localcenterfloatboxfalse
-\newif\ifglobalcenterfloatbox \globalcenterfloatboxfalse
-\newif\ifflushingfloats \flushingfloatsfalse
-\newif\ifpackflushedfloats \packflushedfloatstrue % for the moment
-\newif\ifpackcolumnfloats \packcolumnfloatstrue
-
-\newcount\totalnoffloats
-\newcount\savednoffloats
-\newcount\noffloatinserts
+\newconditional\c_page_floats_room
+\newconditional\c_page_floats_some_waiting
+\newconditional\c_page_floats_not_permitted
+\newconditional\c_page_floats_flushing
+\newconditional\c_page_floats_center_box \settrue\c_page_floats_center_box
+\newconditional\c_page_floats_center_box_local
+\newconditional\c_page_floats_center_box_global
+\newconditional\c_page_floats_pack_flushed \settrue\c_page_floats_pack_flushed
+
+%D For the moment we keep this but they will become private too.
+
+\newcount\totalnoffloats % these will be redone ... handled at the lua end anyway
+\newcount\savednoffloats % these will be redone ... handled at the lua end anyway
\newcount\nofcollectedfloats % communication channel
-\newbox \floatlist
-\newbox \savedfloatlist
+\newcount\noffloatinserts % these will be redone ... handled at the lua end anyway
+
\newbox \floattext
\newdimen\floatwidth
@@ -65,55 +76,55 @@
\appendtoks
\ifcase\savednoffloats
- \global\somefloatwaitingfalse
+ \global\setfalse\c_page_floats_some_waiting
\else
- \global\somefloatwaitingtrue
+ \global\settrue\c_page_floats_some_waiting
\fi
\to \everyfloatscheck
-\def\dofloatsflush#1#2%
+\unexpanded\def\page_floats_flush#1#2%
{\ctxcommand{flushfloat("#1",\number#2)}%
\the\everyfloatscheck}
-\def\dofloatsflushbylabel#1#2%
+\unexpanded\def\page_floats_flush_by_label#1#2%
{\ctxcommand{flushfloat("#1","#2",true)}%
\the\everyfloatscheck}
-\def\dofloatssave#1%
+\unexpanded\def\page_floats_save#1%
{\ctxcommand{savefloat("#1")}%
\the\everyfloatscheck}
-\def\dofloatsresave#1%
+\unexpanded\def\page_floats_resave#1%
{\ctxcommand{resavefloat("#1")}%
\the\everyfloatscheck}
-\def\dopushsavedfloats
+\unexpanded\def\page_floats_push_saved
{\ctxcommand{pushfloat()}%
\the\everyfloatscheck}
-\def\dopopsavedfloats
+\unexpanded\def\page_floats_pop_saved
{\ctxcommand{popfloat()}%
\the\everyfloatscheck}
-\def\dofloatsgetinfo#1%
+\unexpanded\def\page_floats_get_info#1%
{\ctxcommand{consultfloat("#1")}}
-\def\doifelsesavedfloat#1%
+\unexpanded\def\page_floats_if_else#1%
{\ctxcommand{doifelsesavedfloat("#1")}}
-\def\dofloatscollect#1#2#3%
+\unexpanded\def\page_floats_collect#1#2#3%
{\ctxcommand{collectfloat("#1",\number\dimexpr#2,\number\dimexpr#3)}}
-\def\nofstackedfloatincategory#1%
+\unexpanded\def\nofstackedfloatincategory#1%
{\ctxcommand{nofstackedfloats("#1")}}
-\let\dopushcolumnfloats\dopushsavedfloats
-\let\dopopcolumnfloats \dopopsavedfloats
+\let\page_floats_column_push_saved\page_floats_push_saved % overloaded in page-mul
+\let\page_floats_column_pop_saved \page_floats_pop_saved % overloaded in page-mul
-\def\dofloatssavepagefloat#1#2%
+\unexpanded\def\page_floats_save_page_float#1#2%
{\ctxcommand{savefloat("#1", { specification = "#2" })}}
-\def\dofloatssavesomewherefloat#1#2% #1=method
+\unexpanded\def\page_floats_save_somewhere_float#1#2% #1=method
{\ctxcommand{savefloat("#1", { specification = "#2", label = "\floatlabel" })}}
%D This is an experimental new feature (for Alan Braslau), a prelude to more:
@@ -133,19 +144,19 @@
%D \placenamedfloat[figure][beta]
%D \stoptyping
-\def\placenamedfloat
- {\dodoubleargument\doplacenamedfloat}
+\unexpanded\def\placenamedfloat
+ {\dodoubleargument\page_floats_place_named}
-\def\doplacenamedfloat[#1][#2]%
+\def\page_floats_place_named[#1][#2]%
{\doloop
- {\dofloatsflushbylabel\s!somewhere{#2}%
+ {\page_floats_flush_by_label\s!somewhere{#2}%
\ifvoid\floatbox
\exitloop
\else
- \def\currentfloat{#1}%
+ \def {#1}%
\blank[\rootfloatparameter\c!spacebefore]%
\box\floatbox
- \blank[\rootfloatparameter\c!spaceafter]
+ \blank[\rootfloatparameter\c!spaceafter]%
\fi}}
% \setupcaption [figure] [align=flushleft]
@@ -162,10 +173,10 @@
%
% \placefloatwithsetups[somefigure]{}{\externalfigure[dummy][width=5cm,height=2cm]}
-\def\placefloatwithsetups
- {\dotripleempty\doplacefloatwithsetups}
+\unexpanded\def\placefloatwithsetups
+ {\dotripleempty\page_floats_place_with_setups}
-\long\def\doplacefloatwithsetups[#1][#2][#3]#4%
+\def\page_floats_place_with_setups[#1][#2][#3]#4%
{\def\floatsetupcaption {#4}%
\def\floatsetupcontent {\copy\nextbox}%
\def\floatsetupwidth {\wd\nextbox}%
@@ -178,10 +189,10 @@
%D
%D First we reimplement some helpers.
-\def\dogetfloat
- {\ifsomefloatwaiting
- \dofloatsflush\s!text{1}%
- \ifcenterfloatbox
+\unexpanded\def\page_floats_get
+ {\ifconditional\c_page_floats_some_waiting
+ \page_floats_flush\s!text\plusone
+ \ifconditional\c_page_floats_center_box
\ifdim\wd\globalscratchbox<\hsize
\global\setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}%
\else
@@ -198,40 +209,53 @@
\global\setbox\floatbox\emptybox
\fi}
-\def\dosavefloat
- {\dofloatssave\s!text
- \nonoindentation} % brrr nonoindentation here
-
-\def\doresavefloat
- {\dofloatsresave\s!text}
-
-\def\doreversesavefloat
- {\dofloatsresave\s!text}
-
-\def\doflushsavedfloats
+\unexpanded\def\page_floats_flush_saved
{\doloop
- {\ifsomefloatwaiting
+ {\ifconditional\c_page_floats_some_waiting
\page_otr_command_check_if_float_fits
- \ifroomforfloat
- \dogetfloat
+ \ifconditional\c_page_floats_room
+ \page_floats_get
\doplacefloatbox
\else
\exitloop
\fi
\else
-% \ifconditional\c_page_margin_blocks_present % not here, here just as many floats as fit
-% \page_otr_command_flush_margin_blocks
-% \else
+ % \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
\fi}}
+%D This is a future mechamism that will be integrated once we're sure about it:
+%D
+%D \starttyping
+%D \dorecurse{10}
+%D {\input thuan
+%D \placefigure{}{\framed[height=1.5cm]{test}}
+%D \placefloatplaceholder}
+%D \stoptyping
+
+\unexpanded\def\placefloatplaceholder
+ {\ifconditional\c_page_floats_room \else
+ \ifdim\dimexpr\pagegoal-\pagetotal-3\lineheight\relax>\zeropoint
+ \startlinecorrection[blank]
+ \mhbox{\inframed{\labeltexts{placeholder}{\lastcaptiontag}}}%
+ \stoplinecorrection
+ \else
+ \allowbreak
+ \fi
+ \fi}
+
+\setuplabeltext
+ [placeholder={\Word{\lastplacedfloat}~, moved}]
+
%D Page floats use different stacks.
-\newtoks \everybeforeflushedpagefloat
+\newtoks\everybeforeflushedpagefloat
-\def\doflushsomepagefloat#1% future releases can do more clever things
- {\dofloatsflush{#1}{1}%
+\def\page_floats_flush_page_floats_indeed#1% future releases can do more clever things
+ {\page_floats_flush{#1}\plusone
\edef\floatspecification{\ctxcommand{getfloatvariable("specification")}}% Is this okay?
\the\everybeforeflushedpagefloat
\vbox to \textheight
@@ -240,38 +264,15 @@
\doifnotinset\v!low\floatspecification\vfill}%
\page_otr_fill_and_eject_page}
-\def\doflushpagefloats
+\unexpanded\def\page_floats_flush_page_floats % used in postpone
{\edef\m_page_otf_checked_page_float{\ctxcommand{checkedpagefloat()}}% (true) for packed
\ifx\m_page_otf_checked_page_float\empty
% nothing
\else\ifx\m_page_otf_checked_page_float\v!empty
\emptyhbox \page_otr_fill_and_eject_page % why not dummy_page
\else
- \doflushsomepagefloat\m_page_otf_checked_page_float
+ \page_floats_flush_page_floats_indeed\m_page_otf_checked_page_float
\fi\fi}
-
-\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
- \ifhbox\floatbox
- \setbox\scratchbox\hbox
- {\unhbox\floatbox
- \unskip\unskip
- \global\setbox\globalscratchbox\lastbox}%
- \box\globalscratchbox
- \else
- \box\floatbox
- \fi
- \else
- \box\floatbox
- \fi
- \else
- \box\floatbox
- \fi
- \else
- \box\floatbox
- \fi}
% temp hack, needed to prevent floatbox being forgotten during
% output, this will change to using another box for flushing
@@ -291,3 +292,28 @@
\to \everyafteroutput
\protect \endinput
+
+% hm, where is this one used (was in save/restore, see old implementation)
+%
+% \unexpanded\def\uncenteredfloatbox
+% {\ifconditional\c_page_floats_center_box
+% \ifhbox\floatbox\relax % remove centering
+% \ifdim\wd\floatbox=\hsize
+% \ifhbox\floatbox
+% \setbox\scratchbox\hbox
+% {\unhbox\floatbox
+% \unskip\unskip
+% \global\setbox\globalscratchbox\lastbox}%
+% \box\globalscratchbox
+% \else
+% \box\floatbox
+% \fi
+% \else
+% \box\floatbox
+% \fi
+% \else
+% \box\floatbox
+% \fi
+% \else
+% \box\floatbox
+% \fi}
diff --git a/tex/context/base/page-flw.mkiv b/tex/context/base/page-flw.mkiv
index 9afacf584..ec1fa636d 100644
--- a/tex/context/base/page-flw.mkiv
+++ b/tex/context/base/page-flw.mkiv
@@ -14,93 +14,127 @@
\writestatus{loading}{ConTeXt Page Macros / Text Flows}
%D This is high experimental and especially flushing may change (proper
-%D spacing is the driving force here).
+%D spacing is the driving force here). It's an old mechanism used for
+%D playing with stepping through document threads. As it's a simple and
+%D effective mechanism we keep it around. It's not to be confused with
+%D upcoming stream support.
+%D
+%D \starttyping
+%D \setuppapersize [S6]
+%D \setuptolerance [verytolerant,stretch]
+%D \setupfooter [strut=no]
+%D \setupwhitespace[big]
+%D
+%D \setuplayout
+%D [rightedge=5cm,width=fit,margin=0pt,edgedistance=1cm,
+%D footer=4cm,footerdistance=1cm,header=0cm]
+%D
+%D \setuptexttexts [edge][][\vbox{\flushtextflow{alpha}}]
+%D \setupfootertexts[edge][][\vbox{\flushtextflow{beta}}]
+%D \setupfootertexts [\vbox{\flushtextflow{gamma}}][]
+%D
+%D \definetextflow [alfa] [width=\rightedgewidth]
+%D \definetextflow [beta] [width=\rightedgewidth]
+%D \definetextflow [gamma] [width=\footerheight]
+%D
+%D \starttext
+%D
+%D \dorecurse{50}
+%D {\getrandomnumber{\funny}{0}{8}
+%D \ifcase\funny \starttextflow[alfa] \input tufte.tex \stoptextflow
+%D \or \starttextflow[beta] \input knuth.tex \stoptextflow
+%D \or \starttextflow[gamma] \input materie.tex \stoptextflow
+%D \or {\bf TUFTE}\quad \input tufte \par
+%D \or {\bf TUFTE}\quad \input tufte \par
+%D \or {\bf KNUTH}\quad \input knuth \par
+%D \or {\bf KNUTH}\quad \input knuth \par
+%D \or {\bf MATERIE}\quad \input materie \par
+%D \else {\bf MATERIE}\quad \input materie \par
+%D \fi}
+%D
+%D \stoptext
+%D \stoptyping
\unprotect
-\unexpanded\def\definetextflow
- {\dodoubleempty\dodefinetextflow}
+\installcorenamespace{textflow}
+\installcorenamespace{textflowbox}
-\def\dodefinetextflow[#1][#2]% flow settings
- {\iffirstargument
- \doiftextflowcollectorelse{#1}
- {\setbox\textflowcollector{#1}\emptybox}
- {\@EA\newbox\csname\??tx:c:#1\endcsname}%
- \getparameters[\??tx:p:#1]
- [\c!width=\hsize,\c!style=,#2]%
- \fi}
+\installcommandhandler \??textflow {textflow} \??textflow
-\def\textflowparameter#1#2{\csname\??tx:p:#1#2\endcsname}
-\def\textflowcollector #1{\csname\??tx:c:#1\endcsname}
+\setuptextflow
+ [%c!style=,
+ %c!color=,
+ \c!width=\availablehsize]
-\def\doiftextflowcollectorelse#1{\doifdefinedelse{\??tx:c:#1}}
+\appendtoks
+ \ifcsname\??textflowbox\currenttextflow\endcsname
+ \setbox\csname\??textflowbox\currenttextflow\endcsname\emptybox
+ \else
+ \expandafter\newbox\csname\??textflowbox\currenttextflow\endcsname
+ \fi
+\to \everydefinetextflow
-\def\doiftextflowelse#1%
- {\doiftextflowcollectorelse{#1}
- {\ifvoid\textflowcollector{#1}%
- \expandafter\secondoftwoarguments
- \else
- \expandafter\firstoftwoarguments
- \fi}
- {\secondoftwoarguments}}
+\let\b_page_textflow_box\zerocount
-\def\doiftextflow#1%
- {\doiftextflowelse{#1}\firstofoneargument\gobbleoneargument}
+\def\textflowcollector#1%
+ {\csname\??textflowbox#1\endcsname}
+
+\unexpanded\def\doiftextflowcollectorelse#1%
+ {\ifcsname\??textflowbox#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\unexpanded\def\doiftextflowelse#1%
+ {\ifcsname\??textflowbox#1\endcsname
+ \ifvoid\csname\??textflowbox#1\endcsname
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+% \unexpanded\def\doiftextflow#1%
+% {\doiftextflowelse{#1}\firstofoneargument\gobbleoneargument}
\unexpanded\def\starttextflow[#1]%
- {\doiftextflowcollectorelse{#1}
- {\global\setbox\textflowcollector{#1}\vbox
- \bgroup
- \unvbox\textflowcollector{#1}%
- \hsize\textflowparameter{#1}\c!width
- \dousestyleparameter{\textflowparameter{#1}\c!style}%
- \unexpanded\def\stoptextflow{\endgraf\egroup}}
- {\let\stoptextflow\relax}}
+ {\begingroup
+ \edef\currenttextflow{#1}%
+ \ifcsname\??textflowbox\currenttextflow\endcsname
+ \b_page_textflow_box\csname\??textflowbox\currenttextflow\endcsname
+ \global\setbox\b_page_textflow_box\vbox
+ \bgroup
+ \dontcomplain
+ \ifvoid\b_page_textflow_box\else
+ \unvbox\b_page_textflow_box
+ \fi
+ \hsize\textflowparameter\c!width\relax
+ \usetextflowstyleandcolor\c!style\c!color
+ \unexpanded\def\stoptextflow{\endgraf\egroup\endgroup}%
+ \else
+ \let\stoptextflow\endgroup
+ \fi}
-\def\flushtextflow#1%
- {\doiftextflow{#1}
- {\ifdim\ht\textflowcollector{#1}>\vsize
- \setbox\scratchbox\vsplit\textflowcollector{#1} to \vsize
- \unvbox\scratchbox
+\unexpanded\def\flushtextflow#1%
+ {\begingroup
+ \edef\currenttextflow{#1}%
+ \ifcsname\??textflowbox\currenttextflow\endcsname
+ \b_page_textflow_box\csname\??textflowbox\currenttextflow\endcsname
+ \ifvoid\b_page_textflow_box
+ % sorry
+ \else\ifdim\ht\b_page_textflow_box>\vsize
+ \setbox\scratchbox\vsplit\b_page_textflow_box to \vsize
+ \ifvoid\scratchbox\else
+ \unvbox\scratchbox
+ \fi
\else
- \unvbox\textflowcollector{#1}%
- \fi}}
+ \unvbox\b_page_textflow_box
+ \fi\fi
+ \fi
+ \endgroup}
\protect \endinput
-
-% Example (dutch)
-%
-% \stelpapierformaatin [S6]
-% \steltolerantiein [soepel,rek]
-% \stelkleurenin [status=start]
-% \stelvoetin [strut=nee]
-% \stelwitruimtein [groot]
-%
-% \stellayoutin
-% [rechterrand=5cm,breedte=passend,marge=0pt,randafstand=1cm,
-% voet=4cm,voetafstand=1cm,hoofd=0cm]
-%
-% \stelteksttekstenin[rand][][\vbox{\flushtextflow{alpha}}]
-% \stelvoettekstenin [rand][][\vbox{\flushtextflow{beta}}]
-% \stelvoettekstenin [\vbox{\flushtextflow{gamma}}][]
-%
-% \definetextflow [alfa] [breedte=\rechterrandbreedte]
-% \definetextflow [beta] [breedte=\rechterrandbreedte]
-% \definetextflow [gamma] [breedte=\voethoogte]
-%
-% \starttekst
-%
-% \dorecurse{50}
-% {\getrandomnumber{\funny}{0}{8}
-% \ifcase\funny \starttextflow[alfa] \input tufte.tex \stoptextflow
-% \or \starttextflow[beta] \input knuth.tex \stoptextflow
-% \or \starttextflow[gamma] \input materie.tex \stoptextflow
-% \or {\bf TUFTE}\quad \input tufte \par
-% \or {\bf TUFTE}\quad \input tufte \par
-% \or {\bf KNUTH}\quad \input knuth \par
-% \or {\bf KNUTH}\quad \input knuth \par
-% \or {\bf MATERIE}\quad \input materie \par
-% \else {\bf MATERIE}\quad \input materie \par
-% \fi}
-%
-% \stoptekst
diff --git a/tex/context/base/page-grd.mkiv b/tex/context/base/page-grd.mkiv
index e882978ca..281d0bfbe 100644
--- a/tex/context/base/page-grd.mkiv
+++ b/tex/context/base/page-grd.mkiv
@@ -70,9 +70,9 @@
{\hskip\layoutcolumnwidth
\ifnum\recurselevel<\layoutcolumns
\vrule
- \!!height\ht\scratchbox
- \!!depth\dp\scratchbox
- \!!width\layoutcolumndistance
+ \s!height\ht\scratchbox
+ \s!depth \dp\scratchbox
+ \s!width \layoutcolumndistance
\fi}}%
\hskip-\makeupwidth
\fi
diff --git a/tex/context/base/page-imp.mkiv b/tex/context/base/page-imp.mkiv
index 9d0f722fe..5eb587b7b 100644
--- a/tex/context/base/page-imp.mkiv
+++ b/tex/context/base/page-imp.mkiv
@@ -148,8 +148,7 @@
\donetrue
\fi
\else % testen, aangepast / expanded nodig ?
- \normalexpanded{\doifinsetelse{\the\shippedoutpages}{\pagestoshipout}}%
- \donetrue\donefalse
+ \normalexpanded{\doifinsetelse{\the\shippedoutpages}{\pagestoshipout}}\donetrue\donefalse
\fi
\ifdone
\setbox\shipoutscratchbox\hbox{#1}%
diff --git a/tex/context/base/page-inf.mkiv b/tex/context/base/page-inf.mkiv
index 6c220fb31..acfbf26f6 100644
--- a/tex/context/base/page-inf.mkiv
+++ b/tex/context/base/page-inf.mkiv
@@ -24,7 +24,7 @@
\let\currentversioninfo\empty
-\def\setupversion
+\unexpanded\def\setupversion
{\dosingleargument\page_info_setup}
\let\version\setupversion
@@ -52,7 +52,7 @@
{\csname\??layoutinfo#1\endcsname}
\installversioninfo\v!concept
- {\vskip\!!sixpoint
+ {\vskip6\points
\hbox to \makeupwidth
{\infofont
\v!concept:\space\currentdate
@@ -60,7 +60,7 @@
\page_adapts_status_info}}
\installversioninfo\v!file
- {\vskip\!!sixpoint
+ {\vskip6\points
\hbox to \makeupwidth
{\infofont
\getmessage\m!system{27}:\space\currentdate\space
diff --git a/tex/context/base/page-ini.mkiv b/tex/context/base/page-ini.mkiv
index aad08ef3e..fdffa552d 100644
--- a/tex/context/base/page-ini.mkiv
+++ b/tex/context/base/page-ini.mkiv
@@ -56,18 +56,18 @@
\newbox\pagebox
-\ifx\mkprocesscolumncontents\undefined\let\mkprocesscolumncontents\gobbleoneargument\fi
-\ifx\mkprocesspagecontents \undefined\let\mkprocesspagecontents \gobbleoneargument\fi
-\ifx\mkprocessboxcontents \undefined\let\mkprocessboxcontents \gobbleoneargument\fi
+\ifdefined\page_postprocessors_column \else \let\page_postprocessors_column\gobbleoneargument \fi
+\ifdefined\page_postprocessors_page \else \let\page_postprocessors_page \gobbleoneargument \fi
+\ifdefined\page_postprocessors_box \else \let\page_postprocessors_box \gobbleoneargument \fi
%D Floats.
\def\page_otr_flush_all_floats
{%\flushnotes already done
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\begingroup
- \noftopfloats\plusthousand
- \nofbotfloats\zerocount
+ \c_page_floats_n_of_top\plusthousand
+ \c_page_floats_n_of_bottom\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
@@ -104,10 +104,11 @@
\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
+ \strc_pagenumbers_increment_counters % should hook into an every
\page_adapts_synchronize
\page_otr_check_for_pending_inserts
- \doflushspread
+ \page_floats_flush_page_floats % before postponed blocks
+ \page_spread_flush % defined later
\page_postponed_blocks_flush}
% Can't we get rid of this hackery? It's used in some widgets
@@ -215,7 +216,6 @@
{\vbox\bgroup % intercept spurious spaces
\the\everybeforepagebody
\starttextproperties
- \dontshowboxes
\checkmarginblocks
\the\beforeeverypage
\normalexpanded{\global\beforepage\emptytoks\the\beforepage}%
@@ -229,4 +229,32 @@
\the\everyafterpagebody
\egroup}
+\def\doiftopofpageelse
+ {\ifdim\pagegoal=\maxdimen
+ \expandafter\firstoftwoarguments
+ \else\ifdim\pagegoal=\vsize
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+% %D Idea:
+%
+% \newinsert\thispageinsert % <- installinsertion
+%
+% \def\flushatthispage
+% {\bgroup
+% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}%
+% \hbox}
+%
+% \appendtoks
+% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi
+% \to \everyshipout
+%
+% %D Idea:
+%
+% \definemarkedpage[nobackgrounds]
+% \markpage[nobackgrounds]
+% \doifmarkedpageelse{nobackgrounds}
+
\protect \endinput
diff --git a/tex/context/base/page-ins.lua b/tex/context/base/page-ins.lua
new file mode 100644
index 000000000..7f870735d
--- /dev/null
+++ b/tex/context/base/page-ins.lua
@@ -0,0 +1,97 @@
+if not modules then modules = { } end modules ['page-ins'] = {
+ version = 1.001,
+ comment = "companion to page-mix.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ -- public = {
+ -- functions = {
+ -- "inserts.define",
+ -- "inserts.getdata",
+ -- },
+ -- commands = {
+ -- "defineinsertion",
+ -- "inserttionnumber",
+ -- }
+ -- }
+}
+
+-- Maybe we should only register in lua and forget about the tex end.
+
+structures = structures or { }
+structures.inserts = structures.inserts or { }
+local inserts = structures.inserts
+
+local report_inserts = logs.reporter("inserts")
+
+local allocate = utilities.storage.allocate
+
+inserts.stored = inserts.stored or allocate { } -- combining them in one is inefficient in the
+inserts.data = inserts.data or allocate { } -- bytecode storage pool
+
+local variables = interfaces.variables
+local v_page = variables.page
+local v_columns = variables.columns
+local v_firstcolumn = variables.firstcolumn
+local v_lastcolumn = variables.lastcolumn
+local v_text = variables.text
+
+storage.register("structures/inserts/stored", inserts.stored, "structures.inserts.stored")
+
+local data = inserts.data
+local stored = inserts.stored
+
+for name, specification in next, stored do
+ data[specification.number] = specification
+ data[name] = specification
+end
+
+function inserts.define(name,specification)
+ specification.name= name
+ local number = specification.number or 0
+ data[name] = specification
+ data[number] = specification
+ -- only needed at runtime as this get stored in a bytecode register
+ stored[name] = specification
+ if not specification.location then
+ specification.location = v_page
+ end
+ return specification
+end
+
+function inserts.setup(name,settings)
+ local specification = data[name]
+ for k, v in next, settings do
+ -- maybe trace change
+ specification[k] = v
+ end
+ return specification
+end
+
+function inserts.setlocation(name,location) -- a practical fast one
+ data[name].location = location
+end
+
+function inserts.getlocation(name,location)
+ return data[name].location or v_page
+end
+
+function inserts.getdata(name) -- or number
+ return data[name]
+end
+
+function inserts.getname(number)
+ return data[name].name
+end
+
+function inserts.getnumber(name)
+ return data[name].number
+end
+
+-- interface
+
+commands.defineinsertion = inserts.define
+commands.setupinsertion = inserts.setup
+commands.setinsertionlocation = inserts.setlocation
+commands.insertionnumber = function(name) context(data[name].number or 0) end
+
diff --git a/tex/context/base/page-ins.mkiv b/tex/context/base/page-ins.mkiv
index 793e28d4c..a63de0b26 100644
--- a/tex/context/base/page-ins.mkiv
+++ b/tex/context/base/page-ins.mkiv
@@ -13,81 +13,164 @@
\writestatus{loading}{ConTeXt Core Macros / Insertions}
-%D Insertions are special data collections that are associated
-%D to \TEX's internal page builder. When multiple footnote
-%D classes were introduced, I decided to isolate some of the
-%D functionality in a module.
+%D Insertions are special data collections that are associated to \TEX's internal
+%D page builder. When multiple footnote classes were introduced, I decided to
+%D isolate some of the functionality in a module.
+
+\registerctxluafile{page-ins}{1.001}
\unprotect
-\newtoks\@@insertionlist
+%D Because we need to deal with inserts at the \LUA\ end as well,
+%D we provide a proper installer.
-\def\processinsertions{\the\@@insertionlist}
+% Not yet used as we need to adapt some code to this.
-\let\doprocessinsert\gobbleoneargument
+\installcorenamespace{insertion}
+\installcorenamespace{insertionnumber}
-\def\installinsertion#1%
- {\ifdefined#1\else
- \let#1\relax
- \fi
- \ifx#1\relax % permits \csname...\endcsname
- \newinsert#1%
- \count#1\plusthousand
- \skip #1\zeropoint
- \dimen#1\maxdimen
- \appendtoks\doprocessinsert#1\to\@@insertionlist
- \fi}
+\installcommandhandler \??insertion {insertion} \??insertion
-\def\synchronizeinsertions
- {\def\doprocessinsert##1{\ifvoid##1\else\insert##1{\unvbox##1}\fi}%
- \processinsertions}
+\setupinsertion
+ [%c!n=\plusone,
+ %c!distance=\zeropoint,
+ %c!maxheight=\maxdimen,
+ %c!factor=\plusthousand,
+ \c!location=\v!page]
-%D For instance, when we postpone footnotes, we need to save
-%D some data related to the inserts. The next methods are
-%D far from ideal, but better than nothing. We save and
-%D restore box content and associated data independently.
-%D The box content is only restores when non||void.
+\newcount\currentinsertionnumber % This is a count and not a macro !
-\def\backupinsertion#1%
- {\csname\string#1\endcsname}
+\newtoks\t_page_inserts_list
-\def\installbackupinsertion#1%
- {\expandafter\newinsert\csname\string#1\endcsname
- \count\backupinsertion#1\zerocount
- \skip \backupinsertion#1\zeropoint
- \dimen\backupinsertion#1\maxdimen}
+\let\doprocessinsert\relax
-\def\saveinsertionbox#1%
- {\ifdim\ht#1>\zeropoint % hm, actually unknown
- \global\setbox\backupinsertion#1\box#1%
- \else
- \global\setbox\backupinsertion#1\emptybox
- \fi}
+%D Maybe some day we will move settings here.
-\def\restoreinsertionbox#1%
- {\ifvoid\backupinsertion#1\else % if void, we keep the content
- \global\setbox#1\box\backupinsertion#1%
- \fi}
+\unexpanded\def\setcurrentinsertion#1%
+ {\edef\currentinsertion{#1}%
+ \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}
-\def\eraseinsertionbackup#1%
- {\global\setbox\backupinsertion#1\emptybox}
+\def\namedinsertionnumber#1{\csname\??insertionnumber#1\endcsname}
-\def\saveinsertiondata#1%
- {\global\skip \backupinsertion#1\skip #1%
- \global\count\backupinsertion#1\count#1%
- \global\dimen\backupinsertion#1\dimen#1}
+\unexpanded\def\page_inserts_synchronize_registers
+ {\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}
-\def\restoreinsertiondata#1%
- {\global\skip #1\skip \backupinsertion#1%
- \global\count#1\count\backupinsertion#1%
- \global\dimen#1\dimen\backupinsertion#1}
+% for practical reasone we still set these elsewhere but that might chaneg in the future
+%
+% \global\count\currentinsertionnumber\numexpr\insertionparameter\c!factor/\insertionparameter\c!n\relax
+% \global\skip \currentinsertionnumber\insertionparameter\c!distance \relax
+% \global\dimen\currentinsertionnumber\insertionparameter\c!maxheight\relax}
-%D Auxiliary macros:
+\appendtoks
+ \page_inserts_synchronize_registers
+\to \everysetupinsertion
+
+\unexpanded\def\page_inserts_process#1% beware, this addapts currentinsertion !
+ {\edef\currentinsertion{#1}%
+ \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname
+ \doprocessinsert\currentinsertionnumber} % old method
+
+\unexpanded\def\processinsertions
+ {\the\t_page_inserts_list}
-\def\addinsertionheight#1\to#2%
+\unexpanded\def\synchronizeinsertions
+ {\let\doprocessinsert\page_inserts_synchronize
+ \processinsertions}
+
+\unexpanded\def\page_inserts_synchronize#1% yes or no
{\ifvoid#1\else
- \advance#2 1\skip#1\relax
- \advance#2 \ht #1\relax
+ \insert#1{\unvbox#1}%
+ \fi}
+
+\unexpanded\def\doifinsertionelse#1%
+ {\ifcsname\??insertionnumber#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
\fi}
+% \unexpanded\def\startinsertion[#1]%
+% {\insert\csname\??insertionnumber#1\endcsname\bgroup}
+%
+% \unexpanded\def\stopinsertion
+% {\egroup}
+
+% For the moment we use the regular insertion allocator so that users can
+% still define their own insertions (not that they will play nicely with
+% all context mechanisms then). We can use the dimensions at the \LUA\ end
+% so we don't need to pass pass them explicitly. Actually, when we see an
+% insertion node at that end, we already know the number.
+
+\appendtoks
+ \ifx\currentinsertionparent\empty
+ \ifcsname\??insertionnumber\currentinsertion\endcsname
+ % bad news
+ \else
+ \expandafter\newinsert\csname\??insertionnumber\currentinsertion\endcsname
+ \page_inserts_synchronize_registers
+ \ctxcommand{defineinsertion("\currentinsertion",{ number = \number\currentinsertionnumber })}%
+ \t_page_inserts_list\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_page_inserts_list
+ \expandafter\page_inserts_process\csname\??insertionnumber\currentinsertion\endcsname}%
+ \count\currentinsertionnumber\plusthousand
+ \skip \currentinsertionnumber\zeropoint
+ \dimen\currentinsertionnumber\maxdimen
+ \fi
+ \else
+ \expandafter\let\csname\??insertionnumber\currentinsertion\expandafter\endcsname
+ \csname\??insertionnumber\currentinsertionparent\endcsname
+ \fi
+\to \everydefineinsertion
+
+\appendtoks
+ \ctxcommand{setupinsertion("\currentinsertion",{
+ location = "\insertionparameter\c!location",
+ })}%
+\to \everysetupinsertion
+
+\unexpanded\def\page_inserts_set_location#1#2% fast one
+ {\ctxcommand{setinsertionlocation("#1","#2")}}
+
+%D Auxiliary macros:
+
+\def\page_insert_insertion_height#1%
+ {\dimexpr\expandafter\page_insert_insertion_height_indeed\csname\??insertionnumber#1\endcsname\relax}
+
+\def\page_insert_insertion_height_indeed#1%
+ {\ifvoid#1\zeropoint\else1\skip#1+\ht#1\fi}
+
+%D Obsolete:
+
+% \installcorenamespace{insertionbackup}
+%
+% \unexpanded\def\installbackupinsertion#1%
+% {\ifcsname\??insertionbackup\string#1\endcsname \else
+% \expandafter\newinsert\csname\??insertionbackup\string#1\endcsname
+% \count\csname\??insertionbackup\string#1\endcsname\zerocount
+% \skip \csname\??insertionbackup\string#1\endcsname\zeropoint
+% \dimen\csname\??insertionbackup\string#1\endcsname\maxdimen
+% \fi}
+%
+% \unexpanded\def\saveinsertionbox#1% hm, actually unknown
+% {\global\setbox\csname\??insertionbackup\string#1\endcsname
+% \ifdim\ht#1>\zeropoint\box#1\else\emptybox\fi}
+%
+% \unexpanded\def\restoreinsertionbox#1%
+% {\ifvoid\backupinsertion#1\else % if void, we keep the content
+% \global\setbox#1\box\csname\??insertionbackup\string#1\endcsname
+% \fi}
+%
+% \unexpanded\def\eraseinsertionbackup#1%
+% {\global\setbox\csname\??insertionbackup\string#1\endcsname\emptybox}
+%
+% \unexpanded\def\saveinsertiondata#1%
+% {\global\skip \csname\??insertionbackup\string#1\endcsname\skip #1%
+% \global\count\csname\??insertionbackup\string#1\endcsname\count#1%
+% \global\dimen\csname\??insertionbackup\string#1\endcsname\dimen#1}
+%
+% \unexpanded\def\restoreinsertiondata#1%
+% {\global\skip #1\skip \csname\??insertionbackup\string#1\endcsname
+% \global\count#1\count\csname\??insertionbackup\string#1\endcsname
+% \global\dimen#1\dimen\csname\??insertionbackup\string#1\endcsname}
+
\protect \endinput
diff --git a/tex/context/base/page-lay.mkiv b/tex/context/base/page-lay.mkiv
index 78839ea70..febabdac4 100644
--- a/tex/context/base/page-lay.mkiv
+++ b/tex/context/base/page-lay.mkiv
@@ -576,7 +576,7 @@
%\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}%
\page_layouts_synchronize}
-\ifx\page_paper_set_offsets\undefined
+\ifdefined\page_paper_set_offsets \else
\def\page_paper_set_offsets % will move
{\global\paperoffset\v_page_target_offset
@@ -585,8 +585,13 @@
\fi
-\ifdefined\setups \else \unexpanded\def\setups[#1]{\setdefaultpenalties} \fi % still needed?
-\ifdefined\synchronizegridsnapping \else \let\synchronizegridsnapping\relax \fi
+\ifdefined\setups \else
+ \unexpanded\def\setups[#1]{\setdefaultpenalties} % still needed?
+\fi
+
+\ifdefined\synchronizegridsnapping \else
+ \let\synchronizegridsnapping\relax
+\fi
\let\p_page_layouts_width \empty
\let\p_page_layouts_height\empty
@@ -806,7 +811,7 @@
\page_layouts_check_revert
\fi\fi\fi\fi\fi\fi}
-\def\installlayoutmethod#1#2%
+\unexpanded\def\installlayoutmethod#1#2%
{\setgvalue{\??layoutmethod#1}{#2}}
\installlayoutmethod\v!default{\page_layouts_check_default}
@@ -926,8 +931,11 @@
%D \macros
%D {adaptlayout}
+\installcorenamespace{adaptlayout}
\installcorenamespace{pageadaptations}
+\installsetuponlycommandhandler \??adaptlayout {adaptlayout}
+
\newdimen\d_page_adepts_pushed_text_height
\newdimen\d_page_adepts_pushed_footer_height
\newdimen\d_page_adepts_height
@@ -946,27 +954,33 @@
\def\page_adapts_layout_register#1#2%
{\setgvalue{\??pageadaptations#2}{\page_adapts_layout_indeed{#1}}}
+\let\p_adapts_height\zeropoint
+\let\p_adapts_lines \zerocount
+
\def\page_adapts_layout_indeed#1%
- {\getparameters[\??za][\c!height=\zeropoint,\c!lines=0,#1]%
+ {\setupcurrentadaptlayout[\c!height=\zeropoint,\c!lines=\zerocount,#1]%
\page_adepts_push
- \doifelse\@@zaheight\v!max
- {\global\d_page_adepts_height\footerheight}
- {\global\d_page_adepts_height\dimexpr
- \ifnum\@@zalines=\zerocount
- \@@zaheight
+ \edef\p_adapts_height{\adaptlayoutparameter\c!height}%
+ \edef\p_adapts_lines {\adaptlayoutparameter\c!lines}%
+ \ifx\p_adapts_height\v!max
+ \global\d_page_adepts_height\footerheight
+ \else
+ \global\d_page_adepts_height\dimexpr
+ \ifnum\p_adapts_lines=\zerocount
+ \p_adapts_height
\else
- \@@zalines\openlineheight
+ \p_adapts_lines\openlineheight
\fi
\relax
\ifdim\d_page_adepts_height>\footerheight
\global\d_page_adepts_height\footerheight
- \fi}
+ \fi
+ \fi
\global\advance\textheight \d_page_adepts_height
\global\advance\footerheight-\d_page_adepts_height
\showmessage\m!layouts1{\the\d_page_adepts_height,\the\realpageno}%
% this will become a better one (do we need insert correction?)
\page_otr_command_set_vsize
- \global\pagegoal\vsize
%
\page_backgrounds_recalculate
\global\let\page_adepts_push\relax
@@ -1105,33 +1119,50 @@
% #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}
+\def\doifoddpageelse
+ {\ifodd\pagenoshift
+ \expandafter\page_layouts_if_odd_else_yes
+ \else
+ \expandafter\page_layouts_if_odd_else_nop
+ \fi}
+
+\def\page_layouts_if_odd_else_yes
+ {\ifodd\realpageno
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\page_layouts_if_odd_else_nop
+ {\ifodd\realpageno
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
\let\doifonevenpaginaelse\doifoddpageelse
-\def\redoifoddpageelse#1{\doifoddpageelse}
+\def\page_layouts_if_odd_else_again#1{\doifoddpageelse}
\def\doifbothsidesoverruled
{\ifdoublesided
- \expandafter\redoifoddpageelse
+ \expandafter\page_layouts_if_odd_else_again
\else
\expandafter\firstofthreearguments
\fi}
\def\doifbothsides% #1 #2 #3
{\ifdoublesided
- \expandafter\doifbothsidesindeed
+ \expandafter\page_layouts_if_both_sides
\else
\expandafter\firstofthreearguments
\fi}
-\def\doifbothsidesindeed
+\def\page_layouts_if_both_sides
{\ifsinglesided
\expandafter\firstofthreearguments
\else
- \expandafter\redoifoddpageelse
+ \expandafter\page_layouts_if_odd_else_again
\fi}
\newdimen\texthoffset
@@ -1179,12 +1210,12 @@
\def\rightorleftpageaction
{\ifdoublesided
- \expandafter\rightorleftpageactionindeed
+ \expandafter\page_layouts_right_or_left_page_action
\else
\expandafter\firstoftwoarguments
\fi}
-\def\rightorleftpageactionindeed
+\def\page_layouts_right_or_left_page_action
{\ifsinglesided
\expandafter\firstoftwoarguments
\else
diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua
index b830dbbb9..4dec0deec 100644
--- a/tex/context/base/page-lin.lua
+++ b/tex/context/base/page-lin.lua
@@ -134,6 +134,10 @@ function boxed.register(configuration)
return last
end
+function commands.registerlinenumbering(configuration)
+ context(boxed.register(configuration))
+end
+
function boxed.setup(n,configuration)
local d = data[n]
if d then
@@ -152,6 +156,8 @@ function boxed.setup(n,configuration)
return n
end
+commands.setuplinenumbering = boxed.setup
+
local function check_number(n,a,skip,sameline)
local d = data[a]
if d then
@@ -280,3 +286,6 @@ function boxed.stage_two(n,m)
end
end
end
+
+commands.linenumbersstageone = boxed.stage_one
+commands.linenumbersstagetwo = boxed.stage_two
diff --git a/tex/context/base/page-lin.mkiv b/tex/context/base/page-lin.mkiv
index 7b1cbcd94..dd13fb87d 100644
--- a/tex/context/base/page-lin.mkiv
+++ b/tex/context/base/page-lin.mkiv
@@ -26,20 +26,6 @@
%
% we should use normal counters but then we need to sync settings
-% not yet ok, we need to give the top line a proper height
-%
-% \newbox\locallinenumberbox
-%
-% \unexpanded\def\startlocallinenumbering
-% {\setbox\locallinenumberbox\vbox\bgroup
-% \startlinenumbering}
-%
-% \unexpanded\def\stoplocallinenumbering
-% {\stoplinenumbering
-% \egroup
-% \mkdoprocessdeepboxcontents\locallinenumberbox
-% \unvbox\locallinenumberbox}
-
% some line
%
% \startlocallinenumbering
@@ -55,137 +41,96 @@
\definesystemattribute[linenumber] [public]
\definesystemattribute[linereference][public]
-\appendtoksonce \attribute\linenumberattribute \attributeunsetvalue \to \everyforgetall
-\appendtoksonce \attribute\displaymathattribute\plusone \to \everybeforedisplayformula
+\appendtoksonce
+ \attribute\linenumberattribute\attributeunsetvalue
+\to \everyforgetall
\newcount \linenumber % not used
-\newbox \linenumberscratchbox
-\newcount \linenumberchunk
-\newcount \linerefcounter
-\newconstant\linenumbernesting
+\newbox \b_page_lines_scratch
+\newcount \c_page_lines_reference
+\newconstant\c_page_lines_nesting
\newconditional\tracelinenumbering
-\def\mkprocesstextlinenumbers#1#2%
- {\setbox\linenumberscratchbox\vbox
- {\forgetall
- \offinterlineskip
- \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
-\let\makelinenumber\gobblesevenarguments
+\installcorenamespace{linenumberinginstance}
-\newconditional\boxcontentneedsprocessing
+\let\makelinenumber\gobblesevenarguments % used at lua end
-\def\mkdoprocesspagecontents #1{\mkaddtextlinenumbers{#1}\plusone \plusone \zerocount}
-\def\mkdoprocessboxcontents #1{\mkaddtextlinenumbers{#1}\plusone \plusone \zerocount}
-\def\mkdoprocessdeepboxcontents#1{\mkaddtextlinenumbers{#1}\plusone \plusone \plusone }
-\def\mkdoprocesscolumncontents #1{\mkaddtextlinenumbers{#1}\currentcolumn\nofcolumns\zerocount}
+\newconditional\page_postprocessors_needed_box
-\def\mklinenumberparameters
- {continue = "\linenumberparameter\c!continue",
- start = \linenumberparameter\c!start,
- step = \linenumberparameter\c!step,
- method = "\linenumberparameter\c!method",
- tag = "\currentlinenumbering"}
+\unexpanded\def\page_postprocessors_linenumbers_page #1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \zerocount}
+\unexpanded\def\page_postprocessors_linenumbers_box #1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \zerocount}
+\unexpanded\def\page_postprocessors_linenumbers_deepbox#1{\page_lines_add_numbers_to_box{#1}\plusone \plusone \plusone }
+\unexpanded\def\page_postprocessors_linenumbers_column #1{\page_lines_add_numbers_to_box{#1}\currentcolumn\nofcolumns\zerocount}
-\def\mklinenumberupdateparameters
- {continue = "\linenumberparameter\c!continue"}
+\def\page_lines_parameters_regular
+ {continue = "\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi",
+ start = \number\linenumberingparameter\c!start,
+ step = \number\linenumberingparameter\c!step,
+ method = "\linenumberingparameter\c!method",
+ tag = "\currentlinenumbering"}
-\def\mkdefinetextlinenumbering
- {\setxvalue{ln:c:\currentlinenumbering}{\number\cldcontext{nodes.lines.boxed.register({\mklinenumberparameters})}}}
+\def\page_lines_parameters_update
+ {continue = "\ifnum\c_page_lines_mode=\zerocount\v!yes\else\v!no\fi"}
-\def\mkupdatetextlinenumbering
- {\ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:\currentlinenumbering},{\mklinenumberupdateparameters})}}
+\def\page_lines_start_define
+ {\setxvalue{\??linenumberinginstance\currentlinenumbering}{\ctxcommand{registerlinenumbering({\page_lines_parameters_regular})}}}
-\def\mkstarttextlinenumbering#1#2% always when assignment
- {\globallet\mkprocesspagecontents \mkdoprocesspagecontents
- \globallet\mkprocesscolumncontents\mkdoprocesscolumncontents
- \global\settrue\boxcontentneedsprocessing % see core-rul.mkiv
- \edef\currentlinenumbering{#1}%
- \ifcase#2\relax
- \mkupdatetextlinenumbering % continue
- \or
- \mkdefinetextlinenumbering % only when assignment
- \fi
- \attribute\linenumberattribute\getvalue{ln:c:\currentlinenumbering}\relax}
+\def\page_lines_start_update
+ {\ctxcommand{setuplinenumbering(\csname\??linenumberinginstance\currentlinenumbering\endcsname,{\page_lines_parameters_update})}}
-\def\mksetuptextlinenumbering
- {\ifcsname ln:c:\currentlinenumbering\endcsname
- \ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:\currentlinenumbering},{\mklinenumberparameters})}%
+\def\page_lines_setup
+ {\ifcsname \??linenumberinginstance\currentlinenumbering\endcsname
+ \ctxcommand{setuplinenumbering(\csname\??linenumberinginstance\currentlinenumbering\endcsname,{\page_lines_parameters_regular})}%
\fi}
-\def\mkstoptextlinenumbering
- {\attribute\linenumberattribute\attributeunsetvalue}
-
% we could make this a bit more efficient by putting the end reference
% in the same table as the start one but why make things complex ...
-\let\dofinishlinereference\dofinishfullreference
+\let\dofinishlinereference\dofinishfullreference % at lua end
-\def\mksomelinereference#1#2#3%
+\unexpanded\def\page_lines_some_reference#1#2#3%
{\dontleavehmode\begingroup
- \global\advance\linerefcounter\plusone
- \attribute\linereferenceattribute\linerefcounter
+ \global\advance\c_page_lines_reference\plusone
+ \attribute\linereferenceattribute\c_page_lines_reference
#3%
% for the moment we use a simple system i.e. no prefixes etc .. todo: store as number
- \expanded{\strc_references_set_named_reference{line}{#2}{conversion=\linenumberparameter\c!conversion}{\the\linerefcounter}}% kind labels userdata text
+ \normalexpanded{\strc_references_set_named_reference{line}{#2}{conversion=\linenumberingparameter\c!conversion}{\the\c_page_lines_reference}}% kind labels userdata text
\endgroup}
-\def\mkstartlinereference#1{\mksomelinereference{#1}{lr:b:#1}{}\ignorespaces}
-\def\mkstoplinereference #1{\removeunwantedspaces\mksomelinereference{#1}{lr:e:#1}{}}
+\def\page_lines_reference_start#1{\page_lines_some_reference{#1}{lr:b:#1}{}\ignorespaces}
+\def\page_lines_reference_stop #1{\removeunwantedspaces\page_lines_some_reference{#1}{lr:e:#1}{}}
+
+% \def\mklinestartreference#1[#2]{\in{#1}[lr:b:#2]} % not interfaced/ not used
+% \def\mklinestopreference #1[#2]{\in{#1}[lr:e:#2]} % not interfaced/ not used
-\def\mklinestartreference#1[#2]{\in{#1}[lr:b:#2]} % not interfaced
-\def\mklinestopreference #1[#2]{\in{#1}[lr:e:#2]} % not interfaced
+\newif\ifnumberinglines % will change
+\newif\iftypesettinglines % will change
-% high level interface
+\installcorenamespace{linenumbering}
-\newif\ifnumberinglines
-\newif\iftypesettinglines
+\installcommandhandler \??linenumbering {linenumbering} \??linenumbering
-\let\currentlinenumbering\empty
+\setnewconstant\c_page_lines_mode \plusone % 0=continue, 1=restart
+\setnewconstant\c_page_lines_location \plusone % 0=middle, 1=left, 2=right, 3=inner, 4=outer, 5=text, 6=begin, 7=end
+\setnewconstant\c_page_lines_alignment\plusfive % 0=middle, 1=left, 2=right, 5=auto
-\setnewconstant\linenumbermode \plusone % 0=continue, 1=restart
-\setnewconstant\linenumberlocation \plusone % 0=middle, 1=left, 2=right, 3=inner, 4=outer, 5=text, 6=begin, 7=end
-\setnewconstant\linenumberalignment\plusfive % 0=middle, 1=left, 2=right, 5=auto
+\newdimen\d_page_lines_width
+\newdimen\d_page_lines_distance
\newevery \beforeeverylinenumbering \relax
\newevery \aftereverylinenumbering \relax
\newevery \everylinenumber \relax
-\newdimen\linenumberwidth
-\newdimen\linenumberdistance
-
-\unexpanded\def\definelinenumbering
- {\dosingleempty\dodefinelinenumbering}
+\appendtoks
+ \page_lines_setup
+\to \everysetuplinenumbering
-\def\dodefinelinenumbering[#1]%
- {\edef\currentlinenumbering{#1}%
- \mkdefinetextlinenumbering}
-
-\unexpanded\def\setuplinenumbering
- {\dodoubleempty\dosetuplinenumbering}
-
-\def\dosetuplinenumbering[#1][#2]%
- {\ifsecondargument
- \def\currentlinenumbering{#1}%
- \getparameters[\??rn#1][#2]%
- \else
- \let\currentlinenumbering\empty
- \getparameters[\??rn][#1]%
- \fi
- \mksetuptextlinenumbering}
-
-% some day commandhandler
-
-\def\linenumberparameter#1%
- {\csname\??rn\ifcsname\??rn\currentlinenumbering#1\endcsname\currentlinenumbering\fi#1\endcsname}
-
-\unexpanded\def\dolinenumberattributes#1#2%
- {\dousestyleparameter{\linenumberparameter#1}%
- \dousecolorparameter{\linenumberparameter#2}}
+\appendtoks
+ \page_lines_start_define
+\to \everydefinelinenumbering
\setuplinenumbering
[\c!conversion=\v!numbers,
@@ -196,7 +141,7 @@
\c!location=\v!left,
\c!style=,
\c!color=,
- \c!width=2em,
+ \c!width=2\emwidth,
\c!left=,
\c!right=,
\c!command=,
@@ -204,253 +149,314 @@
\c!align=\v!auto]
\definelinenumbering
-
-\unexpanded\def\startlinenumbering
- {\dodoubleempty\dostartlinenumbering}
+ []
% no intermediate changes in values, define a class, otherwise each range
% would need a number
% todo: text
-\expandafter\let\csname\??rn:l:\v!middle \endcsname \zerocount
-\expandafter\let\csname\??rn:l:\v!left \endcsname \plusone
-\expandafter\let\csname\??rn:l:\v!margin \endcsname \plusone
-\expandafter\let\csname\??rn:l:\v!inmargin \endcsname \plusone
-\expandafter\let\csname\??rn:l:\v!inleft \endcsname \plusone
-\expandafter\let\csname\??rn:l:\v!right \endcsname \plustwo
-\expandafter\let\csname\??rn:l:\v!inright \endcsname \plustwo
-\expandafter\let\csname\??rn:l:\v!inner \endcsname \plusthree
-\expandafter\let\csname\??rn:l:\v!outer \endcsname \plusfour
-\expandafter\let\csname\??rn:l:\v!text \endcsname \plusfive
-\expandafter\let\csname\??rn:l:\v!begin \endcsname \plussix
-\expandafter\let\csname\??rn:l:\v!end \endcsname \plusseven
-
-\expandafter\let\csname\??rn:a:\v!middle \endcsname \zerocount
-\expandafter\let\csname\??rn:a:\v!right \endcsname \plusone
-\expandafter\let\csname\??rn:a:\v!flushleft \endcsname \plusone
-\expandafter\let\csname\??rn:a:\v!left \endcsname \plustwo
-\expandafter\let\csname\??rn:a:\v!flushright\endcsname \plustwo
-\expandafter\let\csname\??rn:a:\v!auto \endcsname \plusfive
-
-\def\dostartlinenumbering[#1][#2]% todo: c!continue
+\installcorenamespace{linennumberinglocation}
+\installcorenamespace{linennumberingalternative}
+
+\expandafter\let\csname\??linennumberinglocation\v!middle \endcsname \zerocount
+\expandafter\let\csname\??linennumberinglocation\v!left \endcsname \plusone
+\expandafter\let\csname\??linennumberinglocation\v!margin \endcsname \plusone
+\expandafter\let\csname\??linennumberinglocation\v!inmargin \endcsname \plusone
+\expandafter\let\csname\??linennumberinglocation\v!inleft \endcsname \plusone
+\expandafter\let\csname\??linennumberinglocation\v!right \endcsname \plustwo
+\expandafter\let\csname\??linennumberinglocation\v!inright \endcsname \plustwo
+\expandafter\let\csname\??linennumberinglocation\v!inner \endcsname \plusthree
+\expandafter\let\csname\??linennumberinglocation\v!outer \endcsname \plusfour
+\expandafter\let\csname\??linennumberinglocation\v!text \endcsname \plusfive
+\expandafter\let\csname\??linennumberinglocation\v!begin \endcsname \plussix
+\expandafter\let\csname\??linennumberinglocation\v!end \endcsname \plusseven
+
+\expandafter\let\csname\??linennumberingalternative\v!middle \endcsname \zerocount
+\expandafter\let\csname\??linennumberingalternative\v!right \endcsname \plusone
+\expandafter\let\csname\??linennumberingalternative\v!flushleft \endcsname \plusone
+\expandafter\let\csname\??linennumberingalternative\v!left \endcsname \plustwo
+\expandafter\let\csname\??linennumberingalternative\v!flushright\endcsname \plustwo
+\expandafter\let\csname\??linennumberingalternative\v!auto \endcsname \plusfive
+
+% \startlinenumbering[<startvalue>|continue|settings|name]
+% \startlinenumbering[name][<startvalue>|continue|settings]
+
+\unexpanded\def\startlinenumbering
+ {\dodoubleempty\page_lines_start}
+
+\def\page_lines_start % we stay downward compatible
{\begingroup
- \linenumbermode\plusone
\ifsecondargument
- \def\currentlinenumbering{#1}%
- \doifassignmentelse{#2}
- {\getparameters[\??rn\currentlinenumbering][#2]}
- {\doifnumberelse{#2}% downward compatible
- {\setvalue{\??rn#1\c!start}{#2}}%
- {\doif{#2}\v!continue
- {\getparameters[\??rn\currentlinenumbering][\c!continue=\v!yes]%
- \linenumbermode\zerocount}}}%
+ \expandafter\page_lines_start_two
\else\iffirstargument
- \doifnumberelse{#1}% downward compatible
- {\let\currentlinenumbering\empty
- \setvalue{\??rn\c!start}{#1}}%
- {\doifelse{#1}\v!continue
- {\let\currentlinenumbering\empty
- \getparameters[\??rn\currentlinenumbering][\c!continue=\v!yes]%
- \linenumbermode\zerocount}
- {\def\currentlinenumbering{#1}}}%
- \fi\fi
- \doif{\linenumberparameter\c!continue}\v!yes
- {\linenumbermode\zerocount}%
- \numberinglinestrue
+ \doubleexpandafter\page_lines_start_one
+ \else
+ \doubleexpandafter\page_lines_start_zero
+ \fi\fi}
+
+\def\page_lines_start_zero[#1][#2]%
+ {\edef\m_argument{\linenumberingparameter\c!continue}%
+ \ifx\m_argument\v!continue
+ \c_page_lines_mode\zerocount
+ \else
+ \c_page_lines_mode\plusone
+ \fi
+ \page_lines_start_followup}
+
+\def\page_lines_start_one[#1][#2]% [continue|<number>|settings] % historic
+ {\edef\m_argument{#1}%
+ \ifx\m_argument\v!continue
+ \c_page_lines_mode\zerocount
+ \let\currentlinenumbering\empty
+ \else
+ \c_page_lines_mode\plusone
+ \ifx\m_argument\v!empty
+ \let\currentlinenumbering\empty
+ \else
+ \doifassignmentelse{#1}
+ {\let\currentlinenumbering\empty
+ \setupcurrentlinenumbering[#1]}
+ {\doifnumberelse\m_argument
+ {\let\currentlinenumbering\empty
+ \letlinenumberingparameter\c!start\m_argument}
+ {\let\currentlinenumbering\m_argument}}%
+ \fi
+ \edef\m_argument{\linenumberingparameter\c!continue}%
+ \ifx\m_argument\v!continue
+ \c_page_lines_mode\zerocount
+ \fi
+ \fi
+ \page_lines_start_followup}
+
+\def\page_lines_start_two[#1][#2]% [tag][continue|<number>|settings]
+ {\edef\currentlinenumbering{#1}%
+ \edef\m_argument{#2}%
+ \ifx\m_argument\v!continue
+ \c_page_lines_mode\zerocount
+ \else
+ \c_page_lines_mode\plusone
+ \ifx\m_argument\v!empty \else
+ \doifassignmentelse{#2}
+ {\setupcurrentlinenumbering[#2]}
+ {\doifnumber\m_argument
+ {\letlinenumberingparameter\c!start\m_argument}}%
+ \fi
+ \edef\m_argument{\linenumberingparameter\c!continue}%
+ \ifx\m_argument\v!continue
+ \c_page_lines_mode\zerocount
+ \fi
+ \fi
+ \page_lines_start_followup}
+
+\def\page_lines_start_followup
+ {\numberinglinestrue
\the\beforeeverylinenumbering
- \mkstarttextlinenumbering\currentlinenumbering\linenumbermode}
+ \globallet\page_postprocessors_page \page_postprocessors_linenumbers_page
+ \globallet\page_postprocessors_column\page_postprocessors_linenumbers_column
+ \global\settrue\page_postprocessors_needed_box % see core-rul.mkiv
+ \ifcase\c_page_lines_mode\relax
+ \page_lines_start_update % continue
+ \or
+ \page_lines_start_define % only when assignment
+ \fi
+ \attribute\linenumberattribute\getvalue{\??linenumberinginstance\currentlinenumbering}\relax}
\unexpanded\def\stoplinenumbering
- {\mkstoptextlinenumbering
+ {\attribute\linenumberattribute\attributeunsetvalue
\the\aftereverylinenumbering
\endgroup}
% number placement .. will change into (the new) margin code
-\def\mkdoinnerlinenumber{\doifoddpageelse\mkdoleftlinenumber\mkdorightlinenumber}
-\def\mkdoouterlinenumber{\doifoddpageelse\mkdorightlinenumber\mkdoleftlinenumber}
+\def\page_lines_number_inner_indeed{\doifoddpageelse\page_lines_number_left_indeed\page_lines_number_right_indeed}
+\def\page_lines_number_outer_indeed{\doifoddpageelse\page_lines_number_right_indeed\page_lines_number_left_indeed}
-\def\mkleftlinenumber
- {\ifcase\linenumberlocation
- \expandafter\mkdoleftlinenumber
+\def\page_lines_number_left
+ {\ifcase\c_page_lines_location
+ \expandafter\page_lines_number_left_indeed
\or
- \expandafter\mkdoleftlinenumber
+ \expandafter\page_lines_number_left_indeed
\or
- \expandafter\mkdoleftlinenumber
+ \expandafter\page_lines_number_left_indeed
\or
- \expandafter\mkdoinnerlinenumber
+ \expandafter\page_lines_number_inner_indeed
\or
- \expandafter\mkdoouterlinenumber
+ \expandafter\page_lines_number_outer_indeed
\or
- \expandafter\mkdotextlinenumber
+ \expandafter\page_lines_number_text_indeed
\or
- \expandafter\mkdobeginlinenumber
+ \expandafter\page_lines_number_begin_indeed
\or
- \expandafter\mkdoendlinenumber
+ \expandafter\page_lines_number_end_indeed
\fi}
-\def\mkrightlinenumber
- {\ifcase\linenumberlocation
- \expandafter\mkdorightlinenumber
+\def\page_lines_number_right
+ {\ifcase\c_page_lines_location
+ \expandafter\page_lines_number_right_indeed
\or
- \expandafter\mkdorightlinenumber
+ \expandafter\page_lines_number_right_indeed
\or
- \expandafter\mkdorightlinenumber
+ \expandafter\page_lines_number_right_indeed
\or
- \expandafter\mkdoouterlinenumber
+ \expandafter\page_lines_number_outer_indeed
\or
- \expandafter\mkdoinnerlinenumber
+ \expandafter\page_lines_number_inner_indeed
\or
- \expandafter\mkdotextlinenumber
+ \expandafter\page_lines_number_text_indeed
\or
- \expandafter\mkdoendlinenumber
+ \expandafter\page_lines_number_end_indeed
\or
- \expandafter\mkdobeginlinenumber
+ \expandafter\page_lines_number_begin_indeed
\fi}
-\newconditional\faketextlinenumber
-\newconstant \linenumberbox
-\newconstant \linenumbercolumn
-\newconstant \linenumberlastcolumn
+\newconditional\c_page_lines_fake_number
+\newconstant \b_page_lines_number
+\newconstant \c_page_lines_column
+\newconstant \c_page_lines_last_column
-\def\mkaddtextlinenumbers#1#2#3#4% box col max nesting
+\def\page_lines_add_numbers_to_box#1#2#3#4% box col max nesting
{\bgroup
- \linenumberbox #1\relax
- \linenumbercolumn #2\relax
- \linenumberlastcolumn#3\relax
- \linenumbernesting #4\relax
+ \b_page_lines_number #1\relax
+ \c_page_lines_column #2\relax
+ \c_page_lines_last_column#3\relax
+ \c_page_lines_nesting #4\relax
\fullrestoreglobalbodyfont
- \let\makelinenumber\maketextlinenumber
- \mkprocesstextlinenumbers\linenumberbox\linenumbernesting
+ \let\makelinenumber\page_lines_make_number % used at lua end
+ \setbox\b_page_lines_scratch\vbox
+ {\forgetall
+ \offinterlineskip
+ \ctxcommand{linenumbersstageone(\number\b_page_lines_number,\ifcase\c_page_lines_nesting false\else true\fi)}}%
+ \ctxcommand{linenumbersstagetwo(\number\b_page_lines_number,\number\b_page_lines_scratch)}% can move to lua code
\egroup}
-\def\maketextlinenumber#1#2%
+\let\page_lines_make_number_indeed\relax
+
+\def\page_lines_make_number#1#2%
{\edef\currentlinenumbering{#1}%
\ifcase#2\relax
- \settrue \faketextlinenumber
+ \settrue \c_page_lines_fake_number
\else
- \setfalse\faketextlinenumber
+ \setfalse\c_page_lines_fake_number
\fi
- \linenumberlocation \executeifdefined{\??rn:l:\linenumberparameter\c!location}\plusone % left
- \linenumberalignment\executeifdefined{\??rn:a:\linenumberparameter\c!align }\plusfive % auto
- \ifcase\linenumberlastcolumn\relax
- \settrue \faketextlinenumber
+ \c_page_lines_location \executeifdefined{\??linennumberinglocation \linenumberingparameter\c!location}\plusone \relax % left
+ \c_page_lines_alignment\executeifdefined{\??linennumberingalternative\linenumberingparameter\c!align }\plusfive\relax % auto
+ \ifcase\c_page_lines_last_column\relax
+ \settrue \c_page_lines_fake_number
\or
% one column
- \ifcase\linenumberlocation
- \settrue \faketextlinenumber
- % hm
+ \ifcase\c_page_lines_location
+ \settrue \c_page_lines_fake_number
+ \let\page_lines_make_number_indeed\page_lines_number_fake_indeed
\or
- \let\domakelinenumber\mkleftlinenumber
+ \let\page_lines_make_number_indeed\page_lines_number_left
\or
- \let\domakelinenumber\mkrightlinenumber
+ \let\page_lines_make_number_indeed\page_lines_number_right
\or % inner
- \let\domakelinenumber\mkdoinnerlinenumber
+ \let\page_lines_make_number_indeed\page_lines_number_inner_indeed
\or % outer
- \let\domakelinenumber\mkdoouterlinenumber
+ \let\page_lines_make_number_indeed\page_lines_number_outer_indeed
\or % text
- \let\domakelinenumber\mkdotextlinenumber
+ \let\page_lines_make_number_indeed\page_lines_number_text_indeed
\or
- \let\domakelinenumber\mkdobeginlinenumber
+ \let\page_lines_make_number_indeed\page_lines_number_begin_indeed
\or
- \let\domakelinenumber\mkdoendlinenumber
+ \let\page_lines_make_number_indeed\page_lines_number_end_indeed
\fi
- \else\ifcase\linenumbercolumn\relax
- \settrue \faketextlinenumber
+ \else\ifcase\c_page_lines_column\relax
+ \settrue \c_page_lines_fake_number
\or
- \let\domakelinenumber\mkleftlinenumber
- \ifcase\linenumberlocation\or
- \linenumberlocation\plusone
+ \let\page_lines_make_number_indeed\page_lines_number_left
+ \ifcase\c_page_lines_location\or
+ \c_page_lines_location\plusone
\or
- \linenumberlocation\plustwo
+ \c_page_lines_location\plustwo
\else
- \linenumberlocation\plusone
+ \c_page_lines_location\plusone
\or
- \linenumberlocation\plusone
+ \c_page_lines_location\plusone
\or
- \linenumberlocation\plusone
+ \c_page_lines_location\plusone
\or
- \linenumberlocation\plusone % todo
+ \c_page_lines_location\plusone % todo
\or
- \linenumberlocation\plusone % todo
+ \c_page_lines_location\plusone % todo
\fi
\else
- \let\domakelinenumber\mkrightlinenumber
- \ifcase\linenumberlocation\or
- \linenumberlocation\plustwo
+ \let\page_lines_make_number_indeed\page_lines_number_right
+ \ifcase\c_page_lines_location\or
+ \c_page_lines_location\plustwo
\or
- \linenumberlocation\plusone
+ \c_page_lines_location\plusone
\or
- \linenumberlocation\plustwo
+ \c_page_lines_location\plustwo
\or
- \linenumberlocation\plustwo
+ \c_page_lines_location\plustwo
\or
- \linenumberlocation\plustwo % todo
+ \c_page_lines_location\plustwo % todo
\or
- \linenumberlocation\plustwo % todo
+ \c_page_lines_location\plustwo % todo
\fi
\fi\fi
- \domakelinenumber{#1}}
+ \page_lines_make_number_indeed{#1}}
-\def\mkdotextlinenumber #1#2#3#4#5#6% beware, one needs so compensate for this in the width !
- {\hbox{\dosomelinenumber{#1}{2}{#2}{#5}\hskip#3\scaledpoint}}
+\let\page_lines_number_fake_indeed\gobblesixarguments % needs checking
-\def\mkdotextlinenumber #1#2#3#4#5#6% beware, one needs so compensate for this in the width !
- {\hbox{\dosomelinenumber{#1}{2}{#2}{#5}\hskip#3\scaledpoint}}
+\def\page_lines_number_text_indeed#1#2#3#4#5#6% beware, one needs so compensate for this in the \hsize
+ {\hbox{\page_lines_number_construct{#1}{2}{#2}{#5}\hskip#3\scaledpoint}}
-\def\mkdoleftlinenumber #1#2#3#4#5#6%
+\def\page_lines_number_left_indeed#1#2#3#4#5#6%
{\naturalhbox to \zeropoint
{\ifcase\istltdir#6\else \hskip-#4\scaledpoint \fi
- \llap{\dosomelinenumber{#1}{2}{#2}{#5}\kern#3\scaledpoint}}}
+ \llap{\page_lines_number_construct{#1}{2}{#2}{#5}\kern#3\scaledpoint}}}
-\def\mkdorightlinenumber#1#2#3#4#5#6%
+\def\page_lines_number_right_indeed#1#2#3#4#5#6%
{\naturalhbox to \zeropoint
{\ifcase\istltdir#6\else \hskip-#4\scaledpoint \fi
- \rlap{\hskip#4\scaledpoint\hskip#3\scaledpoint\dosomelinenumber{#1}{1}{#2}{#5}}}}
+ \rlap{\hskip\dimexpr#4\scaledpoint+#3\scaledpoint\relax\page_lines_number_construct{#1}{1}{#2}{#5}}}}
-\def\mkdobeginlinenumber #1#2#3#4#5#6%
+\def\page_lines_number_begin_indeed#1#2#3#4#5#6%
{\ifcase\istltdir#6\relax
- \linenumberlocation\plusone
- \expandafter\mkdoleftlinenumber
+ \c_page_lines_location\plusone
+ \expandafter\page_lines_number_left_indeed
\else
- \linenumberlocation\plustwo
- \expandafter\mkdorightlinenumber
+ \c_page_lines_location\plustwo
+ \expandafter\page_lines_number_left_indeed
\fi{#1}{#2}{#3}{#4}{#5}{#6}}
-\def\mkdoendlinenumber#1#2#3#4#5#6%
+\def\page_lines_number_end_indeed#1#2#3#4#5#6%
{\ifcase\istltdir#6\relax
- \linenumberlocation\plustwo
- \expandafter\mkdorightlinenumber
+ \c_page_lines_location\plustwo
+ \expandafter\page_lines_number_left_indeed
\else
- \linenumberlocation\plusone
- \expandafter\mkdoleftlinenumber
+ \c_page_lines_location\plusone
+ \expandafter\page_lines_number_left_indeed
\fi{#1}{#2}{#3}{#4}{#5}{#6}}
-\def\dosomelinenumber#1#2#3#4% tag 1=left|2=right linenumber leftskip
+\def\page_lines_number_construct#1#2#3#4% tag 1=left|2=right linenumber leftskip
{\begingroup
\def\currentlinenumbering{#1}%
\def\linenumber{#3}% unsafe
- \doifelse{\linenumberparameter\c!width}\v!margin
- {\linenumberwidth\leftmarginwidth}
- {\linenumberwidth\linenumberparameter\c!width}%
- \linenumberdistance\linenumberparameter\c!distance\relax
- \ifcase#2\relax\or\hskip\linenumberdistance\fi\relax
- \ifnum\linenumberlocation=\plusfive
- \scratchdimen\dimexpr#4\scaledpoint-\linenumberdistance\relax
- \linenumberlocation\plusone
+ \doifelse{\linenumberingparameter\c!width}\v!margin
+ {\d_page_lines_width\leftmarginwidth}
+ {\d_page_lines_width\linenumberingparameter\c!width}%
+ \d_page_lines_distance\linenumberingparameter\c!distance\relax
+ \ifcase#2\relax\or\hskip\d_page_lines_distance\fi\relax
+ \ifnum\c_page_lines_location=\plusfive
+ \scratchdimen\dimexpr#4\scaledpoint-\d_page_lines_distance\relax
+ \c_page_lines_location\plusone
\else
\scratchdimen\zeropoint
\fi
- \ifcase\linenumberalignment
- \linenumberlocation\zerocount % middle
+ \ifcase\c_page_lines_alignment
+ \c_page_lines_location\zerocount % middle
\or
- \linenumberlocation\plusone % left
+ \c_page_lines_location\plusone % left
\or
- \linenumberlocation\plustwo % right
+ \c_page_lines_location\plustwo % right
\fi
- \ifconditional\tracelinenumbering\ruledhbox\else\hbox\fi to \linenumberwidth
- {\ifcase\linenumberlocation
+ \ifconditional\tracelinenumbering\ruledhbox\else\hbox\fi to \d_page_lines_width
+ {\ifcase\c_page_lines_location
\hss % middle
\or
% left
@@ -461,16 +467,16 @@
\or
\doifoddpageelse\hss\relax % outer
\fi
- \ifconditional\faketextlinenumber
+ \ifconditional\c_page_lines_fake_number
% we need to reserve space
\else
- \dolinenumberattributes\c!style\c!color
- \linenumberparameter\c!command
- {\linenumberparameter\c!left
- \convertnumber{\linenumberparameter\c!conversion}{#3}%
- \linenumberparameter\c!right}%
+ \uselinenumberingstyleandcolor\c!style\c!color
+ \linenumberingparameter\c!command
+ {\linenumberingparameter\c!left
+ \convertnumber{\linenumberingparameter\c!conversion}{#3}%
+ \linenumberingparameter\c!right}%
\fi
- \ifcase\linenumberlocation
+ \ifcase\c_page_lines_location
\hss % middle
\or
\hss % left
@@ -481,53 +487,60 @@
\or
\doifoddpageelse\relax\hss % outer
\fi}%
- \ifcase#2\relax\or\or\hskip\linenumberdistance\fi\relax
- \hskip-\scratchdimen
+ \ifcase#2\relax
+ \hskip-\scratchdimen
+ \or
+ \hskip-\scratchdimen
+ \or
+ \hskip\dimexpr\d_page_lines_distance-\scratchdimen\relax
+ \fi
+ \relax
\the\everylinenumber
\endgroup}
-% left right inner outer
-
-% align: \alignedline\@@rnalign\v!right{\box0\hskip\@@rndistance}
-
% referencing
-\unexpanded\def\someline [#1]{\mkstartlinereference{#1}\mkstoplinereference{#1}} % was just a def
-\unexpanded\def\startline[#1]{\mkstartlinereference{#1}}
-\unexpanded\def\stopline [#1]{\mkstoplinereference {#1}}
+\unexpanded\def\someline [#1]{\page_lines_reference_start{#1}\page_lines_reference_stop{#1}} % was just a def
+\unexpanded\def\startline[#1]{\page_lines_reference_start{#1}}
+\unexpanded\def\stopline [#1]{\page_lines_reference_stop {#1}}
-\def\mkshowstartlinereference#1%
+\def\page_lines_reference_show_start#1%
{\ifconditional\tracelinenumbering
\setbox\scratchbox\hbox{\llap
- {\vrule\!!width\onepoint\!!depth\strutdp\!!height.8\strutht\raise.85\strutht\hbox{\llap{\tt\txx#1}}}}%
- \smashbox\scratchbox\box\scratchbox
+ {\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht\raise.85\strutht\hbox{\llap{\tt\txx#1}}}}%
+ \smashbox\scratchbox
+ \box\scratchbox
\fi}
-\def\mkshowstoplinereference#1%
+\def\page_lines_reference_show_stop#1%
{\ifconditional\tracelinenumbering
\setbox\scratchbox\hbox{\rlap
- {\raise.85\strutht\hbox{\rlap{\tt\txx#1}}\vrule\!!width\onepoint\!!depth\strutdp\!!height.8\strutht}}%
- \smashbox\scratchbox\box\scratchbox
+ {\raise.85\strutht\hbox{\rlap{\tt\txx#1}}\vrule\s!width\onepoint\s!depth\strutdp\s!height.8\strutht}}%
+ \smashbox\scratchbox
+ \box\scratchbox
\fi}
-\def\mkstartlinereference#1{\mksomelinereference{#1}{lr:b:#1}{\mkshowstartlinereference{#1}}\ignorespaces}
-\def\mkstoplinereference #1{\removeunwantedspaces\mksomelinereference{#1}{lr:e:#1}{\mkshowstoplinereference{#1}}}
+\def\page_lines_reference_start#1{\page_lines_some_reference{#1}{lr:b:#1}{\page_lines_reference_show_start{#1}}\ignorespaces}
+\def\page_lines_reference_stop #1{\removeunwantedspaces\page_lines_some_reference{#1}{lr:e:#1}{\page_lines_reference_show_stop{#1}}}
% eventually we will do this in lua
-\def\currentreferencelinenumber{\ctxlua{structures.references.filter("linenumber")}}
+\def\currentreferencelinenumber{\ctxcommand{filterreference("linenumber")}}
+
+\let\m_page_lines_from\empty
+\let\m_page_lines_to \empty
-\def\doifelsesamelinereference#1#2#3%
+\unexpanded\def\doifelsesamelinereference#1#2#3%
{\doifreferencefoundelse{lr:b:#1}
- {\edef\fline{\currentreferencelinenumber}%
+ {\edef\m_page_lines_from{\currentreferencelinenumber}%
\doifreferencefoundelse{lr:e:#1}
- {\edef\tline{\currentreferencelinenumber}%
- %[\fline,\tline]
- \ifx\fline\tline#2\else#3\fi}
+ {\edef\m_page_lines_to{\currentreferencelinenumber}%
+ %[\m_page_lines_from,\m_page_lines_to]
+ \ifx\m_page_lines_from\m_page_lines_to#2\else#3\fi}
{#2}}
{#2}}
-\def\inline#1[#2]%
+\unexpanded\def\inline#1[#2]%
{\doifelsenothing{#1}
{\doifelsesamelinereference{#2}
{\in{\leftlabeltext\v!line}{\rightlabeltext\v!line}[lr:b:#2]}
@@ -536,9 +549,9 @@
{\in{#1}[lr:b:#2]}
{\in{#1}[lr:b:#2]--\in[lr:e:#2]}}}
-\def\inlinerange[#1]%
+\unexpanded\def\inlinerange[#1]%
{\doifelsesamelinereference{#1}
{\in[lr:b:#1]}
- {\in[lr:b:#1]--\in[lr:e:#1]}}
+ {\in[lr:b:#1]\endash\in[lr:e:#1]}}
\protect \endinput
diff --git a/tex/context/base/page-mak.mkvi b/tex/context/base/page-mak.mkvi
index f37c4f613..6120f56bb 100644
--- a/tex/context/base/page-mak.mkvi
+++ b/tex/context/base/page-mak.mkvi
@@ -88,7 +88,10 @@
\newbox \b_page_makeup
\newtoks\t_page_makeup_every_setup
-\def\page_makeup_start_yes[#name][#settings]%
+\def\page_makeup_start_yes[#name]% [#settings]%
+ {\doifelsecommandhandler\??makeup{#name}\page_makeup_start_indeed\page_makeup_start_nop[#name]}%
+
+\def\page_makeup_start_indeed[#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]}%
@@ -113,22 +116,23 @@
{\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
+ \strc_pagenumbers_page_state_push % new
+ \makeupparameter\c!before\relax
+ \begingroup
+ \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]%
+ \doif{\makeupparameter\c!location}\v!top{\topskip\zeropoint}%
+ \box\b_page_makeup
+ \the\t_page_makeup_every_setup
+ \page
+ \endgroup
+ \makeupparameter\c!after\relax
\ifdoublesided \ifodd\realpageno \else
\getvalue{\??makeupdoublesided\makeupparameter\c!doublesided}%
\fi \fi
- \poppagestate % new
+ \strc_pagenumbers_page_state_pop % new
\egroup
\stoplayout} % includes \page
@@ -166,6 +170,7 @@
%\c!align=,
%\c!before=,
%\c!after=,
+ %\c!location=,
\c!page=\v!right,
\c!doublesided=\v!empty,
\c!top=\vss,
diff --git a/tex/context/base/page-mbk.mkvi b/tex/context/base/page-mbk.mkvi
index eb8061bf3..9e3e57193 100644
--- a/tex/context/base/page-mbk.mkvi
+++ b/tex/context/base/page-mbk.mkvi
@@ -220,9 +220,9 @@
\box\floatbox
\filbreak}%
\ifdim\ht\b_page_margin_blocks>\textheight
- % \dosavefloatinfo % no saving done anyway
+ % page_floats_report_saved % no saving done anyway
\else
- \doinsertfloatinfo
+ \page_floats_report_total
\fi}
\def\page_margin_blocks_process_float_nop
diff --git a/tex/context/base/page-mix.lua b/tex/context/base/page-mix.lua
new file mode 100644
index 000000000..be87b79a7
--- /dev/null
+++ b/tex/context/base/page-mix.lua
@@ -0,0 +1,642 @@
+if not modules then modules = { } end modules ['page-mix'] = {
+ version = 1.001,
+ comment = "companion to page-mix.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- inserts.getname(name)
+
+-- local node, tex = node, tex
+-- local nodes, interfaces, utilities = nodes, interfaces, utilities
+-- local trackers, logs, storage = trackers, logs, storage
+-- local number, table = number, table
+
+local concat = table.concat
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+local nodepool = nodes.pool
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local insert_code = nodecodes.ins
+local mark_code = nodecodes.mark
+
+local new_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+local new_glue = nodepool.glue
+
+local hpack = node.hpack
+local vpack = node.vpack
+local freenode = node.free
+
+local texbox = tex.box
+local texskip = tex.skip
+local texdimen = tex.dimen
+local points = number.points
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local variables = interfaces.variables
+local v_yes = variables.yes
+local v_global = variables["global"]
+local v_local = variables["local"]
+local v_columns = variables.columns
+
+local trace_state = false trackers.register("mixedcolumns.trace", function(v) trace_state = v end)
+local trace_detail = false trackers.register("mixedcolumns.detail", function(v) trace_detail = v end)
+
+local report_state = logs.reporter("mixed columns")
+
+pagebuilders = pagebuilders or { }
+pagebuilders.mixedcolumns = pagebuilders.mixedcolumns or { }
+local mixedcolumns = pagebuilders.mixedcolumns
+
+local forcedbreak = -123
+
+-- initializesplitter(specification)
+-- cleanupsplitter()
+
+-- Inserts complicate matters a lot. In order to deal with them well, we need to
+-- distinguish several cases.
+--
+-- (1) full page columns: firstcolumn, columns, lastcolumn, page
+-- (2) mid page columns : firstcolumn, columns, lastcolumn, page
+--
+-- We need to collect them accordingly.
+
+local function collectinserts(result,nxt,nxtid)
+ local inserts, currentskips, nextskips, inserttotal = { }, 0, 0, 0
+ while nxt do
+ if nxtid == insert_code then
+ inserttotal = inserttotal + nxt.height + nxt.depth
+ local s = nxt.subtype
+-- print(">>>",structures.inserts.getlocation(s))
+ local c = inserts[s]
+ if not c then
+ c = { }
+ inserts[s] = c
+ local width = texskip[s].width
+ if not result.inserts[s] then
+ currentskips = currentskips + width
+ end
+ nextskips = nextskips + width
+ end
+ c[#c+1] = nxt
+ if trace_detail then
+ report_state("insert of class %s found",s)
+ end
+ elseif nxtid == mark_code then
+ if trace_detail then
+ report_state("mark found")
+ end
+ else
+ break
+ end
+ nxt = nxt.next
+ if nxt then
+ nxtid = nxt.id
+ else
+ break
+ end
+ end
+ return nxt, inserts, currentskips, nextskips, inserttotal
+end
+
+local function appendinserts(ri,inserts)
+ for class, collected in next, inserts do
+ local ric = ri[class]
+ if not ric then
+ -- assign to collected
+ ri[class] = collected
+ else
+ -- append to collected
+ for j=1,#collected do
+ ric[#ric+1] = collected[j]
+ end
+ end
+ end
+end
+
+local function discardtopglue(current,discarded)
+ while current do
+ local id = current.id
+ if id == glue_code or (id == penalty_code and current.penalty ~= forcedbreak) then
+ discarded[#discarded+1] = current
+ current = current.next
+ else
+ break
+ end
+ end
+ return current
+end
+
+local function stripbottomglue(results,discarded)
+ local height = 0
+ for i=1,#results do
+ local r = results[i]
+ local t = r.tail
+ while t and t ~= r.head do
+ local prev = t.prev
+ if not prev then
+ break
+ elseif t.id == penalty_code then
+ if t.penalty == forcedbreak then
+ break
+ else
+ discarded[#discarded+1] = t
+ r.tail = prev
+ t = prev
+ end
+ elseif t.id == glue_code then
+ discarded[#discarded+1] = t
+ r.height = r.height - t.spec.width
+ r.tail = prev
+ t = prev
+ else
+ break
+ end
+ end
+ if r.height > height then
+ height = r.height
+ end
+ end
+ return height
+end
+
+local function setsplit(specification) -- a rather large function
+ local box = specification.box
+ if not box then
+ report_state("fatal error, no box")
+ return
+ end
+ local list = texbox[box]
+ if not list then
+ report_state("fatal error, no list")
+ return
+ end
+ local head = list.head or specification.originalhead
+ if not head then
+ report_state("fatal error, no head")
+ return
+ end
+ local discarded = { }
+ local originalhead = head
+ local originalwidth = specification.originalwidth or list.width
+ local originalheight = specification.originalheight or list.height
+ local current = head
+ local height = 0
+ local depth = 0
+ local skip = 0
+ local options = settings_to_hash(specification.option or "")
+ local stripbottom = specification.alternative == v_local
+ local cycle = specification.cycle or 1
+ local nofcolumns = specification.nofcolumns or 1
+ if nofcolumns == 0 then
+ nofcolumns = 1
+ end
+ local preheight = specification.preheight or 0
+ local extra = specification.extra or 0
+ local maxheight = specification.maxheight
+ local optimal = originalheight/nofcolumns
+ if specification.balance ~= v_yes then
+ optimal = maxheight
+ end
+ local target = optimal + extra
+ local overflow = target > maxheight - preheight
+ local threshold = specification.threshold or 0
+ if overflow then
+ target = maxheight - preheight
+ end
+ if trace_state then
+ report_state("cycle: %s, maxheight: %s, preheight: %s, target: %s, overflow: %s, extra: %s",
+ cycle, points(maxheight),points(preheight),points(target),tostring(overflow),points(extra))
+ end
+ local results = { }
+ for i=1,nofcolumns do
+ results[i] = {
+ head = false,
+ tail = false,
+ height = 0,
+ depth = 0,
+ inserts = { },
+ delta = 0,
+ }
+ end
+ local column = 1
+ local result = results[column]
+ local lasthead = nil
+ local rest = nil
+ local function gotonext()
+ if head == lasthead then
+ if trace_state then
+ report_state("empty column %s, needs more work",column)
+ end
+rest = current
+return false
+ else
+ lasthead = head
+ result.head = head
+ if current == head then
+ result.tail = head
+ else
+ result.tail = current.prev
+ end
+ result.height = height
+ result.depth = depth
+ end
+ head = current
+ height = 0
+ depth = 0
+ skip = 0
+ if column == nofcolumns then
+ column = 0 -- nicer in trace
+ rest = head
+-- lasthead = head
+ return false
+ else
+ column = column + 1
+ result = results[column]
+ current = discardtopglue(current,discarded)
+ head = current
+-- lasthead = head
+ return true
+ end
+ end
+ local function checked(advance)
+ local total = skip + height + depth + advance
+ local delta = total - target
+ if trace_detail then
+ local currentcolumn = column
+ local state
+ if delta > threshold then
+ result.delta = delta
+ if gotonext() then
+ state = "next"
+ else
+ state = "quit"
+ end
+ else
+ state = "same"
+ end
+ if trace_detail then
+ report_state("check > column %s, advance: %s, total: %s, target: %s => %s (height: %s, depth: %s, skip: %s)",
+ currentcolumn,points(advance),points(total),points(target),state,points(height),points(depth),points(skip))
+ end
+ return state
+ else
+ if delta > threshold then
+ result.delta = delta
+ if gotonext() then
+ return "next"
+ else
+ return "quit"
+ end
+ else
+ return "same"
+ end
+ end
+ end
+ current = discardtopglue(current,discarded)
+ head = current
+ while current do
+ local id = current.id
+ local nxt = current.next
+ if id == hlist_code or id == vlist_code then
+ local nxtid = nxt and nxt.id
+ local inserts, currentskips, nextskips, inserttotal = nil, 0, 0, 0
+ local advance = current.height -- + current.depth
+ if nxt and (nxtid == insert_code or nxtid == mark_code) then
+ nxt, inserts, localskips, insertskips, inserttotal = collectinserts(result,nxt,nxtid)
+ end
+ local state = checked(advance+inserttotal+currentskips)
+ if trace_state then
+ report_state('line > column %s, advance: %s, insert: %s, height: %s, state: %s',
+ column,points(advance),points(inserttotal),points(height),state)
+ end
+ if state == "quit" then
+ break
+ else
+ height = height + depth + skip + advance + inserttotal
+ if state == "next" then
+ height = height + nextskips
+ else
+ height = height + currentskips
+ end
+ end
+ depth = current.depth
+ skip = 0
+ if inserts then
+ appendinserts(result.inserts,inserts)
+ end
+ elseif id == glue_code then
+ local advance = current.spec.width
+ if advance ~= 0 then
+ local state = checked(advance)
+ if trace_state then
+ report_state('glue > column %s, advance: %s, height: %s, state: %s',
+ column,points(advance),points(height),state)
+ end
+ if state == "quit" then
+ break
+ end
+ height = height + depth + skip
+ depth = 0
+ skip = height > 0 and advance or 0
+ end
+ elseif id == kern_code then
+ local advance = current.kern
+ if advance ~= 0 then
+ local state = checked(advance)
+ if trace_state then
+ report_state('kern > column %s, advance: %s, height: %s, state: %s',
+ column,points(advance),points(height),state)
+ end
+ if state == "quit" then
+ break
+ end
+ height = height + depth + skip + advance
+ depth = 0
+ skip = 0
+ end
+ elseif id == penalty_code then
+ local penalty = current.penalty
+ if penalty == 0 then
+ -- don't bother
+ elseif penalty == forcedbreak then
+ if gotonext() then
+ if trace_state then
+ report_state("cycle: %s, forced column break (same page)",cycle)
+ end
+ else
+ if trace_state then
+ report_state("cycle: %s, forced column break (next page)",cycle)
+ end
+ break
+ end
+ else
+ -- todo: nobreak etc ... we might need to backtrack so we need to remember
+ -- the last acceptable break
+ -- club and widow and such i.e. resulting penalties (if we care)
+ end
+ end
+ if nxt then
+ current = nxt
+ elseif head == lasthead then
+ -- to be checked but break needed as otherwise we have a loop
+ if trace_state then
+ report_state("quit as head is lasthead")
+ end
+ break
+ else
+ local r = results[column]
+ r.head = head
+ r.tail = current
+ r.height = height
+ r.depth = depth
+ break
+ end
+ end
+ if not current then
+ if trace_state then
+ report_state("nilling rest")
+ end
+ rest = nil
+ elseif rest == lasthead then
+ if trace_state then
+ report_state("nilling rest as rest is lasthead")
+ end
+ rest = nil
+ end
+
+ if stripbottom then
+ local height = stripbottomglue(results,discarded)
+ if height > 0 then
+ target = height
+ end
+ end
+
+ specification.results = results
+ specification.height = target
+ specification.originalheight = originalheight
+ specification.originalwidth = originalwidth
+ specification.originalhead = originalhead
+ specification.targetheight = target or 0
+ specification.rest = rest
+ specification.overflow = overflow
+ specification.discarded = discarded
+
+ texbox[specification.box].head = nil
+
+ return specification
+end
+
+function mixedcolumns.finalize(result)
+ if result then
+ local results = result.results
+ for i=1,result.nofcolumns do
+ local r = results[i]
+ local h = r.head
+ if h then
+ h.prev = nil
+ local t = r.tail
+ if t then
+ t.next = nil
+ else
+ h.next = nil
+ r.tail = h
+ end
+ for c, list in next, r.inserts do
+ local t = { }
+ for i=1,#list do
+ local l = list[i]
+ local h = new_hlist()
+ t[i] = h
+ h.head = l.head
+ h.height = l.height
+ h.depth = l.depth
+ l.head = nil
+ end
+ t[1].prev = nil -- needs checking
+ t[#t].next = nil -- needs checking
+ r.inserts[c] = t
+ end
+ end
+ end
+ end
+end
+
+local splitruns = 0
+
+local function report_deltas(result,str)
+ local t = { }
+ for i=1,result.nofcolumns do
+ t[#t+1] = points(result.results[i].delta or 0)
+ end
+ report_state("%s, cycles: %s, deltas: %s",str,result.cycle or 1,concat(t," | "))
+end
+
+function mixedcolumns.setsplit(specification)
+ splitruns = splitruns + 1
+ if trace_state then
+ report_state("split run %s",splitruns)
+ end
+ local result = setsplit(specification)
+ if result then
+ if result.overflow then
+ if trace_state then
+ report_deltas(result,"overflow")
+ end
+ -- we might have some rest
+ elseif result.rest and specification.balance == v_yes then
+ local step = specification.step or 65536*2
+ local cycle = 1
+ local cycles = specification.cycles or 100
+ while result.rest and cycle <= cycles do
+ specification.extra = cycle * step
+ result = setsplit(specification) or result
+ if trace_state then
+ report_state("cycle: %s.%s, original height: %s, total height: %s",
+ splitruns,cycle,points(result.originalheight),points(result.nofcolumns*result.targetheight))
+ end
+ cycle = cycle + 1
+ specification.cycle = cycle
+ end
+ if cycle > cycles then
+ report_deltas(result,"too many balancing cycles")
+ elseif trace_state then
+ report_deltas(result,"balanced")
+ end
+ elseif trace_state then
+ report_deltas(result,"done")
+ end
+ return result
+ elseif trace_state then
+ report_state("no result")
+ end
+end
+
+local topskip_code = gluecodes.topskip
+local baselineskip_code = gluecodes.baselineskip
+
+function mixedcolumns.getsplit(result,n)
+ if not result then
+ report_state("flush, column: %s, no result",n)
+ return
+ end
+ local r = result.results[n]
+ if not r then
+ report_state("flush, column: %s, empty",n)
+ end
+ local h = r.head
+ if not h then
+ return new_glue(result.originalwidth)
+ end
+
+ if trace_state then
+ local id = h.id
+ if id == hlist_code then
+ report_state("flush, column: %s, top line: %s",n,nodes.toutf(h.list))
+ else
+ report_state("flush, column: %s, head node: %s",n,nodecodes[id])
+ end
+ end
+
+ h.prev = nil -- move up
+ local strutht = result.strutht
+ local strutdp = result.strutdp
+ local lineheight = strutht + strutdp
+
+ local v = new_vlist()
+ v.head = h
+
+ -- local v = vpack(h,"exactly",height)
+
+ v.width = result.originalwidth
+ if result.alternative == v_global then -- option
+ result.height = result.maxheight
+ end
+ v.height = lineheight * math.ceil(result.height/lineheight) - strutdp
+ v.depth = strutdp
+
+ for c, list in next, r.inserts do
+ -- tex.setbox("global",c,vpack(nodes.concat(list)))
+ -- tex.setbox(c,vpack(nodes.concat(list)))
+ texbox[c] = vpack(nodes.concat(list))
+ r.inserts[c] = nil
+ end
+ return v
+end
+
+function mixedcolumns.getrest(result)
+ local rest = result and result.rest
+ result.rest = nil -- to be sure
+ return rest
+end
+
+function mixedcolumns.getlist(result)
+ local originalhead = result and result.originalhead
+ result.originalhead = nil -- to be sure
+ return originalhead
+end
+
+function mixedcolumns.cleanup(result)
+ local discarded = result.discarded
+ for i=1,#discarded do
+ freenode(discarded[i])
+ end
+end
+
+-- interface --
+
+local result
+
+function commands.mixsetsplit(specification)
+ if result then
+ for k, v in next, specification do
+ result[k] = v
+ end
+ result = mixedcolumns.setsplit(result)
+ else
+ result = mixedcolumns.setsplit(specification)
+ end
+end
+
+function commands.mixgetsplit(n)
+ if result then
+ context(mixedcolumns.getsplit(result,n))
+ end
+end
+
+function commands.mixfinalize()
+ if result then
+ mixedcolumns.finalize(result)
+ end
+end
+
+function commands.mixflushrest()
+ if result then
+ context(mixedcolumns.getrest(result))
+ end
+end
+
+function commands.mixflushlist()
+ if result then
+ context(mixedcolumns.getlist(result))
+ end
+end
+
+function commands.mixstate()
+ context(result and result.rest and 1 or 0)
+end
+
+function commands.mixcleanup()
+ if result then
+ mixedcolumns.cleanup(result)
+ result = nil
+ end
+end
diff --git a/tex/context/base/page-mix.mkiv b/tex/context/base/page-mix.mkiv
new file mode 100644
index 000000000..a4ef619bb
--- /dev/null
+++ b/tex/context/base/page-mix.mkiv
@@ -0,0 +1,771 @@
+%D \module
+%D [ file=page-mix,
+%D version=2012.07.12,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Mixed Columns,
+%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 / Mixed Columns}
+
+%D This is a very experimental module. Eventually it will replace the current
+%D multi column mechanism (that then will be an instance). The \LUA\ part of
+%D the interface will quite probably change so don't use that one directly
+%D (yet).
+
+% todo:
+%
+% consult note class
+% notes per page
+% notes in each column
+% notes in last column
+% notes local/global
+% top and bottom inserts
+% wide floats
+% move floats
+
+% luatex buglet:
+%
+% \ctxlua{tex.setbox("global",0,node.hpack(nodes.pool.glyph("a",font.current())))}\box0
+
+\registerctxluafile{page-mix}{1.001}
+
+\unprotect
+
+%D The mixed output routine replaces the traditional multi column handler that
+%D started out in \MKII. One of the complications of a routine is that it needs
+%D to align nicely when mixed in a single column layout. Instead of using all
+%D kind of shift juggling in this mechanism we simply switch to grid mode
+%D locally. After all, columns don't look nice when not on a grid. As the grid
+%D snapper in \MKIV\ is more advanced not that much extra code is needed.
+
+%D We use the command handler but the parent settings are not to be changed.
+%D Instead we could have used a dedicated root setup, but it's not worth the
+%D trouble.
+
+\installcorenamespace{mixedcolumns}
+
+\def\s!mixedcolumn{mixedcolumn}
+
+\installframedcommandhandler \??mixedcolumns {mixedcolumns} \??mixedcolumns
+
+\setupmixedcolumns
+ [\c!distance=1.5\bodyfontsize,
+ \c!n=\plustwo,
+ %\c!rule=\v!none,
+ \c!frame=\v!off,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay,
+ \c!alternative=\v!local,
+ \c!maxheight=\textheight,
+ \c!maxwidth=\makeupwidth,
+ \c!step=.25\lineheight, % needs some experimenting
+ \c!method=\ifinner\s!box\else\s!otr\fi] % automatic as suggested by WS
+
+\let\startmixedcolumns\relax % defined later
+\let\stopmixedcolumns \relax % defined later
+
+\appendtoks
+ \setuevalue{\e!start\currentmixedcolumns}{\startmixedcolumns[\currentmixedcolumns]}%
+ \setuevalue{\e!stop \currentmixedcolumns}{\stopmixedcolumns}%
+\to \everydefinemixedcolumns
+
+%D In order to avoid a mixup we use quite some local registers.
+
+\newdimen \d_page_mix_column_width
+\newdimen \d_page_mix_max_height
+\newdimen \d_page_mix_max_width
+\newdimen \d_page_mix_distance
+\newcount \c_page_mix_n_of_columns
+\newdimen \d_page_mix_threshold
+\newdimen \d_page_mix_leftskip
+\newdimen \d_page_mix_rightskip
+
+\newdimen \d_page_mix_balance_step
+\setnewconstant\c_page_mix_balance_cycles 500
+
+\setnewconstant\c_page_mix_break_forced -123
+
+\newbox \b_page_mix_preceding
+\newdimen \d_page_mix_preceding_height
+
+\newbox \b_page_mix_collected
+
+\newconstant \c_page_mix_routine
+
+\setnewconstant\c_page_mix_routine_regular \zerocount
+\setnewconstant\c_page_mix_routine_intercept\plusone
+\setnewconstant\c_page_mix_routine_continue \plustwo
+\setnewconstant\c_page_mix_routine_balance \plusthree
+\setnewconstant\c_page_mix_routine_error \plusfour
+
+%D The main environment is called as follows:
+%D
+%D \starttyping
+%D \startmixedcolumns[instance][settings]
+%D \startmixedcolumns[instance]
+%D \startmixedcolumns[settings]
+%D \stoptyping
+%D
+%D However, best is not to use this one directly but define an instance and
+%D use that one.
+
+% % For the moment only on my machine:
+%
+% \definemixedcolumns
+% [\v!columns]
+%
+% \unexpanded\def\setupcolumns
+% {\setupmixedcolumns[\v!columns]}
+
+%D In itemizations we also need columns, so let's define a apecial instance
+%D for them. These need to work well in situations like this:
+%D
+%D \starttyping
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two,packed][before=,after=]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two][before=,after=]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D
+%D \startnarrower
+%D \startitemize[columns,two]
+%D \dorecurse{10}{\startitem item #1 \stopitem}
+%D \stopitemize
+%D \stopnarrower
+%D
+%D \input zapf
+%D \stoptyping
+
+\ifdefined\s!itemgroupcolumns \else \def\s!itemgroupcolumns{itemgroupcolumns} \fi
+
+\definemixedcolumns
+ [\s!itemgroupcolumns]
+ [\c!n=\itemgroupparameter\c!n,
+ \c!rule=\v!off,
+ \c!balance=\v!yes]
+
+\unexpanded\def\strc_itemgroups_start_columns
+ {\startmixedcolumns[\s!itemgroupcolumns]} % we could have a fast one
+
+\unexpanded\def\strc_itemgroups_stop_columns
+ {\stopmixedcolumns}
+
+%D The mixed output routine can be in different states. First we need to intercept
+%D the already present content. This permits mixed single and multi column usage.
+%D Then we have the continuous routine, one that intercepts pages in sequence.
+%D Finally, when we finish the mixed columns mode, we can (optionally) balance the
+%D last page.
+
+\unexpanded\def\page_mix_command_routine
+ {\ifcase\c_page_mix_routine
+ \page_one_command_routine
+ \or
+ \page_mix_routine_intercept
+ \or
+ \page_mix_routine_continue
+ \or
+ \page_mix_routine_balance
+ \or
+ \page_mix_routine_error
+ \fi}
+
+%D The interceptor is quite simple, at least for the moment.
+
+\def\page_mix_routine_intercept
+ {\global\setbox\b_page_mix_preceding\vbox
+ {\page_otr_command_flush_top_insertions
+ \unvbox\normalpagebox}}
+
+%D The error routine is there but unlikely to be called. It is a left-over from
+%D the traditional routine that might come in handy some day.
+
+\def\page_mix_routine_error
+ {\showmessage\m!columns3\empty
+ \page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+%D Some settings (and actions) depend on the current output routine and setting the
+%D hsize and vsize is among them. The calculation of the hsize is done elsewhere.
+
+\unexpanded\def\page_mix_command_set_hsize
+ {\hsize\d_page_mix_column_width}
+
+%D When setting the vsize we make sure that we collect a few more lines than needed
+%D so that we have enough to split over the columns. Collecting too much is somewhat
+%D tricky as they will spill over to the next page.
+
+\unexpanded\def\page_mix_command_set_vsize
+ {\vsize\dimexpr\c_page_mix_n_of_columns\textheight+\c_page_mix_n_of_columns\lineheight\relax
+ \pagegoal\vsize}
+
+%D As we use \LUA\ there is the usual amount of tracing at that end. At the tex end
+%D we only visualize boxes.
+
+\let\page_mix_hbox\hbox
+\let\page_mix_vbox\vbox
+
+\installtextracker
+ {mixedcolumns.boxes}
+ {\let\page_mix_hbox\ruledhbox
+ \let\page_mix_vbox\ruledvbox}
+ {\let\page_mix_hbox\hbox
+ \let\page_mix_vbox\vbox}
+
+%D We provide a few column break options. Interesting is that while forcing a new
+%D column in the traditional mechanism was a pain, here it works quite well.
+
+\installcolumnbreakmethod \s!mixedcolumn \v!preference
+ {\goodbreak}
+
+\installcolumnbreakmethod \s!mixedcolumn \v!yes
+ {\penalty\c_page_mix_break_forced\relax}
+
+%D As we operate in grid snapping mode, we use a dedicated macro to enable this
+%D mechamism.
+
+\def\page_mix_enable_grid_snapping
+ {\gridsnappingtrue
+ \setsystemmode\v!grid
+ \spac_grids_snap_value_set\v!yes}
+
+%D Between columns there is normally just spacing unless one enforces a rule.
+%D
+%D \starttyping
+%D \input zapf
+%D
+%D \startnarrower
+%D \startmixedcolumns[n=2,background=color,backgroundcolor=red,rulethickness=1mm,rulecolor=green,separator=rule]
+%D \input zapf
+%D \stopmixedcolumns
+%D \stopnarrower
+%D
+%D \input zapf
+%D \stoptyping
+
+\installcorenamespace{mixedcolumnsseparator}
+
+\setvalue{\??mixedcolumnsseparator\v!rule}%
+ {\starttextproperties
+ \usemixedcolumnscolorparameter\c!rulecolor
+ \vrule\s!width\mixedcolumnsparameter\c!rulethickness
+ \stoptextproperties}
+
+\unexpanded\def\page_mix_command_inject_separator
+ {\bgroup
+ \hss
+ \csname\??mixedcolumnsseparator\mixedcolumnsparameter\c!separator\endcsname
+ \hss
+ \egroup}
+
+%D We've now arrived at the real code. The start command mostly sets up the
+%D environment and variables that are used in the splitter. One of the last
+%D things happening at the start is switching over to the mixed continuous
+%D routine.
+
+\installcorenamespace{mixedcolumnsbefore}
+\installcorenamespace{mixedcolumnsstart}
+\installcorenamespace{mixedcolumnsstop}
+\installcorenamespace{mixedcolumnsafter}
+
+%D For practical reasons there is always a first argument needed that
+%D indicates the class.
+%D
+%D \starttyping
+%D \startmixedcolumns[n=3,alternative=global]
+%D \dorecurse{200}{Zomaar wat #1 met een footnote\footnote{note #1}. }
+%D \stopmixedcolumns
+%D \stoptyping
+
+\unexpanded\def\startmixedcolumns
+ {\dodoubleempty\page_mix_start_columns}
+
+\unexpanded\def\page_mix_start_columns
+ {\pushmacro\currentmixedcolumns
+ \pushmacro\currentmixedcolumnsmethod
+ \ifsecondargument
+ \singleexpandafter\page_mix_start_columns_a
+ \else\iffirstargument
+ \doubleexpandafter\page_mix_start_columns_b
+ \else
+ \doubleexpandafter\page_mix_start_columns_c
+ \fi\fi}
+
+\def\page_mix_start_columns_a[#1][#2]%
+ {\edef\currentmixedcolumns{#1}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax
+ \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \setupcurrentmixedcolumns[#2]%
+ \page_mix_initialize_columns
+ \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname}
+
+\def\page_mix_start_columns_b[#1][#2]%
+ {\doifassignmentelse{#1}%
+ {\let\currentmixedcolumns\empty
+ \page_mix_error_b}
+ {\edef\currentmixedcolumns{#1}%
+ \firstargumentfalse}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax % so, it doesn't list to local settings !
+ \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \iffirstargument
+ \setupcurrentmixedcolumns[#1]%
+ \fi
+ \page_mix_initialize_columns
+ \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} % no \relax
+
+\def\page_mix_error_b
+ {\writestatus\m!columns{best use an instance of mixed columns}}
+
+\def\page_mix_start_columns_c[#1][#2]%
+ {\let\currentmixedcolumns\empty
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax
+ \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \page_mix_initialize_columns
+ \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname}
+
+\unexpanded\def\page_mix_fast_columns_start#1%
+ {\pushmacro\currentmixedcolumns
+ \pushmacro\currentmixedcolumnsmethod
+ \edef\currentmixedcolumns{#1}%
+ \edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
+ \mixedcolumnsparameter\c!before\relax % so, it doesn't list to local settings !
+ \csname\??mixedcolumnsbefore\currentmixedcolumnsmethod\endcsname\relax
+ \begingroup
+ \page_mix_initialize_columns
+ \csname\??mixedcolumnsstart\currentmixedcolumnsmethod\endcsname} % no \relax
+
+%D When we stop, we switch over to the balancing routine. After we're done we
+%D make sure to set the sizes are set, a somewhat redundant action when we
+%D already have flushed but better be safe.
+
+\unexpanded\def\stopmixedcolumns
+ {\csname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax
+ \endgroup
+ \csname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax
+ \mixedcolumnsparameter\c!after\relax
+ \popmacro\currentmixedcolumnsmethod
+ \popmacro\currentmixedcolumns}
+
+% \unexpanded\def\stopmixedcolumns
+% {\csname\??mixedcolumnsstop \currentmixedcolumnsmethod\endcsname % no \relax
+% \endgroup
+% \csname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax
+% \mixedcolumnsparameter\c!after\relax
+% \ifx\currentmixedcolumnsmethod\s!otr
+% \popmacro\currentmixedcolumnsmethod
+% \popmacro\currentmixedcolumns
+% \synchronizeoutput % brrr, otherwise sometimes issues in itemize
+% \else
+% \popmacro\currentmixedcolumnsmethod
+% \popmacro\currentmixedcolumns
+% \fi
+% }
+
+\let\page_mix_fast_columns_stop\stopmixedcolumns
+
+%D This is how the fast one is used:
+
+\unexpanded\def\strc_itemgroups_start_columns
+ {\page_mix_fast_columns_start\s!itemgroupcolumns}
+
+\let\strc_itemgroups_stop_columns\page_mix_fast_columns_stop
+
+%D The common initialization:
+
+\def\page_mix_initialize_columns
+ {\page_mix_enable_grid_snapping
+ %
+ \d_page_mix_distance \mixedcolumnsparameter\c!distance
+ \c_page_mix_n_of_columns\mixedcolumnsparameter\c!n
+ \d_page_mix_max_height \mixedcolumnsparameter\c!maxheight
+ \d_page_mix_max_width \mixedcolumnsparameter\c!maxwidth
+ \d_page_mix_balance_step\mixedcolumnsparameter\c!step
+ %
+ \d_page_mix_max_width\dimexpr\d_page_mix_max_width-\leftskip-\rightskip\relax
+ \d_page_mix_leftskip \leftskip
+ \d_page_mix_rightskip\rightskip
+ \leftskip \zeropoint
+ \rightskip\zeropoint
+ %
+ \d_page_mix_threshold\zeropoint
+ %
+ \d_page_mix_column_width\dimexpr(\d_page_mix_max_width-\d_page_mix_distance*\numexpr(\c_page_mix_n_of_columns-\plusone)\relax)/\c_page_mix_n_of_columns\relax
+ %
+ \usemixedcolumnscolorparameter\c!color
+ %
+ \nofcolumns\c_page_mix_n_of_columns} % public
+
+%D The otr method related hooks are defined next:
+
+% \setvalue{\??mixedcolumnsbefore\s!otr}%
+% {\par
+% \ifdim\pagetotal=\zeropoint \else
+% \verticalstrut % probably no longer needed
+% \vskip-\struttotal % probably no longer needed
+% \fi}
+
+\newcount\c_page_mix_otr_nesting
+
+\setvalue{\??mixedcolumnsbefore\s!otr}%
+ {\par
+ \global\advance\c_page_mix_otr_nesting\plusone
+ \ifcase\c_page_mix_otr_nesting\or
+ \ifdim\pagetotal=\zeropoint \else
+ \obeydepth % we could handle this in pre material
+ \fi
+ \fi}
+
+\setvalue{\??mixedcolumnsstart\s!otr}%
+ {\ifcase\c_page_mix_otr_nesting\or
+ \setupoutputroutine[\s!mixedcolumn]%
+ \c_page_mix_routine\c_page_mix_routine_intercept
+ \page_otr_trigger_output_routine
+ %
+ \holdinginserts\maxdimen
+ %
+ \global\d_page_mix_preceding_height\ht\b_page_mix_preceding
+ \c_page_mix_routine\c_page_mix_routine_continue
+ %
+ \page_mix_command_set_vsize
+ \page_mix_command_set_hsize
+ \fi}
+
+\setvalue{\??mixedcolumnsstop\s!otr}%
+ {\par
+ \ifcase\c_page_mix_otr_nesting\or
+ \c_page_mix_routine\c_page_mix_routine_balance
+ \page_otr_trigger_output_routine
+ \fi}
+
+\setvalue{\??mixedcolumnsafter\s!otr}%
+ {\ifcase\c_page_mix_otr_nesting\or
+ \prevdepth\strutdp
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize
+ \fi
+ \global\advance\c_page_mix_otr_nesting\minusone}
+
+%D The splitting and therefore balancing is done at the \LUA\ end. This gives
+%D more readable code and also makes it easier to deal with insertions like
+%D footnotes. Eventually we will have multiple strategies available.
+
+\unexpanded\def\page_mix_routine_construct#1%
+ {\ctxcommand{mixsetsplit {
+ box = \number\b_page_mix_collected,
+ nofcolumns = \number\c_page_mix_n_of_columns,
+ maxheight = \number\d_page_mix_max_height,
+ step = \number\d_page_mix_balance_step,
+ cycles = \number\c_page_mix_balance_cycles,
+ preheight = \number\d_page_mix_preceding_height,
+ prebox = \number\b_page_mix_preceding,
+ strutht = \number\strutht,
+ strutdp = \number\strutdp,
+ threshold = \number\d_page_mix_threshold,
+ balance = "#1",
+ alternative = "\mixedcolumnsparameter\c!alternative",
+ }}%
+ \deadcycles\zerocount}
+
+\unexpanded\def\page_mix_routine_package
+ {\ctxcommand{mixfinalize()}%
+ \setbox\b_page_mix_collected\vbox \bgroup
+ \ifvoid\b_page_mix_preceding \else
+ \box\b_page_mix_preceding
+ \global\d_page_mix_preceding_height\zeropoint
+ \nointerlineskip
+ \fi
+ \hskip\d_page_mix_leftskip
+ \page_mix_hbox to \d_page_mix_max_width \bgroup
+ \letmixedcolumnsparameter\c!strut\v!no
+ % maybe use \c_page_mix_used_of_columns
+ \dorecurse\c_page_mix_n_of_columns {%
+ \inheritedmixedcolumnsframed{\page_mix_command_package_column}%
+ \ifnum\recurselevel<\c_page_mix_n_of_columns
+ \page_mix_command_inject_separator
+ \fi
+ }%
+ \egroup
+ \egroup}
+
+\unexpanded\def\page_mix_command_package_column
+ {\page_mix_hbox to \d_page_mix_column_width \bgroup
+ % maybe intercept empty
+ \ctxcommand{mixgetsplit(\recurselevel)}%
+ \hskip-\d_page_mix_column_width
+ \page_mix_hbox to \d_page_mix_column_width \bgroup
+ \placenoteinserts
+ \hss
+ \egroup
+ \egroup}
+
+\unexpanded\def\page_mix_routine_continue
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \setbox\b_page_mix_collected\vbox{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
+ \page_mix_routine_construct\v!no
+ \page_mix_routine_package
+ \page_otr_construct_and_shipout\box\b_page_mix_collected
+ \ctxcommand{mixflushrest()}%
+ \ctxcommand{mixcleanup()}%
+ \egroup}
+
+\unexpanded\def\page_mix_routine_balance
+ {\bgroup
+ \forgetall
+ \dontcomplain
+ \setbox\b_page_mix_collected\vbox{\unvbox\normalpagebox}% brrr we need to make a tight box (combine this in lua)
+ \doloop
+ {%writestatus\m!columns{construct continue (\the\htdp\b_page_mix_collected)}%
+ \page_mix_routine_construct\v!no
+ \ifcase\ctxcommand{mixstate()}\relax
+ % 0 = okay, we can balance
+ \setbox\b_page_mix_collected\vbox{\ctxcommand{mixflushlist()}}% we could avoid this
+ %writestatus\m!columns{construct balance}%
+ \page_mix_routine_construct\v!yes
+ \page_mix_routine_package
+ \c_page_mix_routine\c_page_mix_routine_regular
+ % \setupoutputroutine[\s!singlecolumn]%
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize
+ \par
+ %writestatus\m!columns{flush balance}%
+ \box\b_page_mix_collected
+ \vskip\zeropoint % triggers recalculation of page stuff (weird that this is needed but it *is* needed, see mixed-001.tex)
+ \par
+ \nointerlineskip
+ \prevdepth\strutdp
+ \ctxcommand{mixflushrest()}% rubish
+ \ctxcommand{mixcleanup()}% rubish
+ \exitloop
+ \or
+ % 1 = we have stuff left, so flush and rebalance
+ %writestatus\m!columns{flush continue}%
+ \page_mix_routine_package
+ \page_otr_construct_and_shipout\box\b_page_mix_collected
+ \setbox\b_page_mix_collected\vbox{\ctxcommand{mixflushrest()}}% we could avoid this
+ \ctxcommand{mixcleanup()}%
+ \ifdim\ht\b_page_mix_collected=\zeropoint
+ \exitloop
+ \fi
+ \fi}%
+ \egroup}
+
+%D We also implement a variant compatible with the so called simple columns
+%D mechanism:
+%D
+%D \starttyping
+%D \startboxedcolumns
+%D \input zapf
+%D \stopboxedcolumns
+%D \stoptyping
+%D
+%D This is a rather mininimalistic variant.
+
+% Maybe we also need a variant with obeydepth before and prevdepth after so
+% that we get a nice spacing.
+
+\definemixedcolumns
+ [boxedcolumns]
+ [\c!balance=\v!yes,
+ \c!n=2,
+ \c!method=\s!box,
+ \c!strut=\v!yes,
+ \c!maxwidth=\availablehsize]
+
+%D Boxed columns can be used nested:
+%D
+%D \starttyping
+%D \setupmixedcolumns
+%D [boxedcolumns]
+%D [n=2,
+%D background=color,
+%D backgroundcolor=darkred,
+%D color=white,
+%D backgroundoffset=1mm]
+%D
+%D \definemixedcolumns
+%D [nestedboxedcolumns]
+%D [boxedcolumns]
+%D [n=2,
+%D background=color,
+%D backgroundcolor=white,
+%D color=darkred,
+%D strut=yes,
+%D backgroundoffset=0mm]
+%D
+%D \startboxedcolumns
+%D \input zapf \par \input ward \par \obeydepth
+%D \startnestedboxedcolumns
+%D \input zapf
+%D \stopnestedboxedcolumns
+%D \par \input zapf \par \obeydepth
+%D \startnestedboxedcolumns
+%D \input zapf
+%D \stopnestedboxedcolumns
+%D \par \input zapf
+%D \stopboxedcolumns
+%D \stoptyping
+
+%D Next we define the hooks:
+
+\letvalue{\??mixedcolumnsbefore\s!box}\donothing
+\letvalue{\??mixedcolumnsafter \s!box}\donothing
+
+\setvalue{\??mixedcolumnsstart\s!box}%
+ {\edef\p_page_mix_strut{\mixedcolumnsparameter\c!strut}%
+ \setbox\b_page_mix_collected\vbox\bgroup
+ \let\currentoutputroutine\s!mixedcolumn % makes \column work
+ \forgetall
+ \page_mix_command_set_hsize
+ \ifx\p_page_mix_strut\v!yes
+ \begstrut
+ \ignorespaces
+ \fi}
+
+\setvalue{\??mixedcolumnsstop\s!box}%
+ {\ifx\p_page_mix_strut\v!yes
+ \removeunwantedspaces
+ \endstrut
+ \fi
+ \egroup
+ \page_mix_box_balance}
+
+%D The related balancer is only a few lines:
+
+\unexpanded\def\page_mix_box_balance
+ {\bgroup
+ \dontcomplain
+ \page_mix_routine_construct\v!yes
+ \page_mix_routine_package
+ \dontleavehmode\box\b_page_mix_collected
+ \ctxcommand{mixflushrest()}%
+ \ctxcommand{mixcleanup()}%
+ \egroup}
+
+%D As usual, floats complicates matters and this is where experimental code
+%D starts.
+
+\let\page_mix_command_package_contents\page_one_command_package_contents
+\let\page_mix_command_flush_float_box \page_one_command_flush_float_box
+
+\unexpanded\def\page_mix_command_check_if_float_fits
+ {\ifpostponecolumnfloats
+ \global\setfalse\c_page_floats_room
+ \else\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
+ \else
+% \bgroup
+% \getcolumnstatus{\count255}{\dimen0}{\dimen2}%
+% \page_floats_get_info\s!text
+% \setbox\scratchbox\vbox % tricky met objecten ?
+% {\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
+% \global\setfalse\c_page_floats_room
+% \else
+ \global\settrue\c_page_floats_room
+ \fi
+ \ifdim\floatwidth>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\setfalse\c_page_floats_room
+ \fi}
+
+\unexpanded\def\page_mix_command_flush_floats
+ {\page_one_command_flush_floats}
+
+\unexpanded\def\page_mix_command_flush_saved_floats
+ {\page_one_command_flush_saved_floats}
+
+% \unexpanded\def\page_mix_command_flush_top_insertions
+% {\page_one_command_flush_top_insertions}
+
+% \unexpanded\def\page_mix_place_float_top
+% {\showmessage\m!columns4\empty\page_one_place_float_here}
+
+% \unexpanded\def\page_mix_place_float_bottom
+% {\showmessage\m!columns5\empty\page_one_place_float_here}
+
+\unexpanded\def\page_mix_place_float_here
+ {\page_one_place_float_here}
+
+\unexpanded\def\page_mix_place_float_force
+ {\page_one_place_float_force}
+
+\unexpanded\def\page_mix_command_side_float_output % hm
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+\unexpanded\def\page_mix_command_synchronize_side_floats % hm
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mix_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mix_command_next_page
+ {\page_otr_eject_page}
+
+\unexpanded\def\page_mix_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
+
+%D We need to hook some handlers into the output routine and we define
+%D a dedicated one:
+
+\defineoutputroutine
+ [\s!mixedcolumn]
+ [\s!page_otr_command_routine =\page_mix_command_routine,
+ \s!page_otr_command_package_contents =\page_mix_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_mix_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_mix_command_set_hsize,
+ \s!page_otr_command_next_page =\page_mix_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_mix_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_mix_command_synchronize_hsize,
+ % \s!page_otr_command_set_top_insertions =\page_mix_command_set_top_insertions,
+ % \s!page_otr_command_set_bottom_insertions =\page_mix_command_set_bottom_insertions,
+ % \s!page_otr_command_flush_top_insertions =\page_mix_command_flush_top_insertions,
+ % \s!page_otr_command_flush_bottom_insertions=\page_mix_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_mix_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_mix_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_mix_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats=\page_mix_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_mix_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_mix_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_mix_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_mix_command_flush_saved_floats
+ % \s!page_otr_command_flush_margin_blocks =\page_mix_command_flush_margin_blocks, % not used
+ ]
+
+%D Only a few float placement options are supported:
+
+\installfloatmethod \s!mixedcolumn \v!here \page_mix_place_float_here
+\installfloatmethod \s!mixedcolumn \v!force \page_mix_place_float_force
+\installfloatmethod \s!mixedcolumn \v!top \page_mix_place_float_top
+\installfloatmethod \s!mixedcolumn \v!bottom \page_mix_place_float_bottom
+
+\installfloatmethod \s!mixedcolumn \v!local \somelocalfloat
+
+%D It ends here.
+
+\protect \endinput
diff --git a/tex/context/base/page-mul.mkiv b/tex/context/base/page-mul.mkiv
index 3792f06ee..1d1698764 100644
--- a/tex/context/base/page-mul.mkiv
+++ b/tex/context/base/page-mul.mkiv
@@ -11,35 +11,21 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% SEE PAGE-MUL-NEW.MKIV
+% todo: basecolumns as parent for columns and itemize
-% BEWARE: TEMPORARY ISSUES WITH VSIZE AND HSIZE BUT WILL BE REDONE
+% !!! there are some issues with hsize an vsize as well as flushing
+% !!! floats but this module will be redone anyway
\writestatus{loading}{ConTeXt Page Macros / Simple Multi Column}
-%D This module is mostly a copy from the original multi column
-%D routine as implemented in \type {core-mul}. When the main
-%D OTR macro's were isolated in modules and column sets were
-%D introduced, this module became part of the OTR modules. As
-%D a result this module is no longer generic. It also needs
-%D an overhaul.
+%D This module is mostly a copy from the original multi column routine as
+%D implemented in \type {core-mul}. When the main OTR macro's were
+%D isolated in modules and column sets were introduced, this module became
+%D part of the OTR modules. As a result this module is no longer generic.
\unprotect
-\unexpanded\def\page_mul_command_side_float_output
- {\page_otr_construct_and_shipout\unvbox\normalpagebox}
-
-\unexpanded\def\page_mul_command_flush_side_floats
- {\page_sides_forget_floats}
-
-\unexpanded\def\page_mul_command_synchronize_side_floats
- {\page_sides_forget_floats}
-
-\unexpanded\def\page_mul_command_next_page
- {\page_otr_eject_page}
-
-\unexpanded\def\page_mul_command_next_page_and_inserts
- {\page_otr_eject_page_and_flush_inserts}
+\definesystemvariable {ks} % KolomSpan
% check \count<insert> multiplications
@@ -47,7 +33,7 @@
%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 considered all calls to Platt's \type{\page_mul_routine_error} 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
@@ -56,7 +42,7 @@
%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 optional balancing without \type{\page_mul_routine_errors}
%D \item different \type{\baselineskips}, \type{\spacing}, \type {\topskip} and
%D \type {\maxdepth}
%D \item left- and right indentation, e.g. within lists
@@ -70,83 +56,147 @@
%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 multi||column mode and
-%D for going to the next column:
-%D
-%D \interface \type{\beginmulticolumns} \\ \\
-%D \interface \type{\endmulticolumns} \\ \\
-%D \interface \type{\ejectcolumn} \\ \\
-\def\finalcolumntextwidth {\makeupwidth}
-\def\finalcolumntextheight {\textheight}
-\def\columntextwidth {\makeupwidth}
-\def\columntextheight {\textheight}
-\def\usercolumnwidth {\textwidth}
-\def\columntextoffset {\!!zeropoint}
+\installcorenamespace {columns}
+
+\installcommandhandler \??columns {columns} \??columns
+
+%D Going to a new columns is done by means of a \type {\ejectcolumn}. The
+%D following definition does not always work.
+
+ \unexpanded\def\ejectcolumn % not good enough
+ {\goodbreak
+ \showmessage\m!columns2\empty}
-\def\fixedcolumnheight {\textheight}
-\def\betweencolumns {\hskip\bodyfontsize}
+%D The output routines plug into a more generic mechanism as can be seen at the
+%D end of this file. So, occasionally we need to define some plugin code.
-\let\setcolumnfloats \relax % in CONTEXT used for floats
-\let\flushcolumnfloats \relax % in CONTEXT used for floats
-\let\flushcolumnfloat \relax % in CONTEXT used for floats
-\let\finishcolumnbox \relax % in CONTEXT used for backgrounds
+\unexpanded\def\page_mul_place_float_top
+ {\showmessage\m!columns4\empty\page_one_place_float_here}
-%D Both macros are redefined in \CONTEXT\ when backgrounds are applied to
-%D columns. The final values are used when flushing the columns.
+\unexpanded\def\page_mul_place_float_bottom
+ {\showmessage\m!columns5\empty\page_one_place_float_here}
-%D It's more convenient to use \type {\columnwidth} instead of messing around
-%D with boxes each time.
+\unexpanded\def\page_mul_place_float_here
+ {\page_one_place_float_here}
-\newdimen\columnwidth
-\newdimen\gutterwidth
+\unexpanded\def\page_mul_place_float_force
+ {\page_one_place_float_force}
-\def\determinecolumnwidth
+\unexpanded\def\page_mul_command_side_float_output
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
+
+\unexpanded\def\page_mul_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mul_command_synchronize_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_mul_command_next_page
+ {\page_otr_eject_page}
+
+\unexpanded\def\page_mul_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
+
+\let\page_mul_initialize_floats\relax
+\let\page_mul_flush_floats \relax
+\let\page_mul_flush_float \relax
+
+%D A hook:
+
+ \let\finishcolumnbox\relax
+
+%D This will change to a local one:
+
+\ifdefined\nofcolumns \else \newcount\nofcolumn \fi
+\ifdefined\mofcolumns \else \newcount\mofcolumn \fi
+
+\appendtoks
+ \nofcolumns\columnsparameter\c!n\relax
+\to \everysetupcolumns
+
+%D Columns are separated by spacing or rules or whatever suits.
+
+\installcorenamespace{columnseparators}
+
+\setvalue{\??columnseparators\v!on }{\let\page_mul_between_columns\page_mul_between_columns_rule}
+\setvalue{\??columnseparators\v!off }{\let\page_mul_between_columns\page_mul_between_columns_space}
+\setvalue{\??columnseparators }{\let\page_mul_between_columns\page_mul_between_columns_space}
+\setvalue{\??columnseparators\s!unknown}{\let\page_mul_between_columns\p_page_mul_rule}
+
+\def\page_mul_between_columns_rule
{\bgroup
- \setbox\scratchbox\hbox
- {\page_mul_command_set_hsize
- \global\columnwidth\usercolumnwidth
- \global\gutterwidth\intercolumnwidth}%
+ \starttextproperties
+ \scratchdistance\dimexpr\columnsparameter\c!distance/2\relax
+ \hskip\scratchdistance\relax
+ \vrule
+ \s!width\linewidth
+ \ifnum\bottomraggednessmode=\plustwo % baselinebottom
+ \s!depth\strutdepth
+ \fi
+ \hskip\scratchdistance\relax
+ \stoptextproperties
\egroup}
-%D Going to a new columns is done by means of a \type {\ejectcolumn}. The
-%D following definition does not always work.
+\def\page_mul_between_columns_space
+ {\hskip\columnsparameter\c!distance\relax}
-\def\ejectcolumn
- {\goodbreak
- \showmessage\m!columns2\empty}
+\let\page_mul_between_columns\page_mul_between_columns_space
-\def\balancingerror
- {\showmessage\m!columns3\empty
- \page_otr_construct_and_shipout\unvbox\normalpagebox}
+%D We declare some registers:
+
+\newdimen \d_page_mul_available_width
+\newdimen \d_page_mul_distance
+\newdimen \d_page_mul_leftskip
+\newdimen \d_page_mul_rightskip
+\newdimen \d_page_mul_offset
+\newdimen \d_page_mul_forced_height
+\newdimen \d_page_mul_used_width
+\newdimen \d_page_mul_temp
-\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}
+\newcount \c_page_mul_balance_minimum
+\newcount \c_page_mul_n_of_lines
-%D The local column width is available in the dimension register \type
-%D {\localcolumnwidth}, which is calculated as:
+\newbox \b_page_mul_preceding
+\newdimen \d_page_mul_preceding_height
+\newdimen \d_page_mul_preceding_depth
+\newconditional\c_page_mul_preceding_present
+
+\newbox \b_page_mul_preceding_rest_of_page
+
+\newconditional\c_page_mul_reverse
+
+\newconditional\c_page_mul_trace
+
+%D The next dimensions reports the final column height .. todo
+
+ \newdimen\finalcolumnheights
+ \newcount\finalcolumnlines
+
+ \newdimen\savedpagetotal % brrr
+
+ \newif\ifstretchcolumns \stretchcolumnsfalse
+ \newif\ifheightencolumns \heightencolumnsfalse
+ \newif\ifinheritcolumns \inheritcolumnsfalse
+ \newif\ifbalancecolumns %\balancecolumnstrue
+
+%D An important one:
\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
- \advance\localcolumnwidth -\leftskip
- \advance\localcolumnwidth -\rightskip
- % new
- \advance\localcolumnwidth -\colleftskip
- \advance\localcolumnwidth -\colrightskip
- %
- \advance\localcolumnwidth -\nofcolumns\intercolumnwidth
- \advance\localcolumnwidth \intercolumnwidth
- \divide \localcolumnwidth \nofcolumns
- \scratchdimen\columntextoffset
- \multiply\scratchdimen \plustwo
- \advance\localcolumnwidth -\scratchdimen
- \usercolumnwidth\localcolumnwidth
- \hsize\localcolumnwidth} % we don't do it \global
+ {\setbox\scratchbox\hbox{\page_mul_between_columns}%
+ \d_page_mul_distance\wd\scratchbox
+ \d_page_mul_available_width\dimexpr
+ \makeupwidth
+ -\d_page_mul_leftskip
+ -\d_page_mul_rightskip
+ -\nofcolumns\d_page_mul_distance
+ +\d_page_mul_distance
+ \relax
+ \d_page_mul_used_width\dimexpr
+ \d_page_mul_available_width/\nofcolumns
+ -\d_page_mul_offset*\plustwo
+ \relax
+ \hsize\d_page_mul_used_width}
%D Torture test:
%D
@@ -217,122 +267,79 @@
%D in||between material, these dimensions are influenced by bodyfont switches inside
%D multi||column mode.
-\newdimen\mcscratchdimen
-\newcount\nofcolumnlines
+\setnewconstant\multicolumnlinemethod\zerocount % 0=normal 1=raw
-\setnewconstant\multicolumnlinemethod\plusone % 0: overshoot (old default), 1: tight
+\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
-\def\getmulticolumnlines
- {\mcscratchdimen-\columntextoffset
- \multiply\mcscratchdimen \plustwo
- \advance\mcscratchdimen \columntextheight
- \ifdim\precolumnboxheight>\zeropoint
- \advance\mcscratchdimen -\precolumnboxheight
- \fi
- \settotalinsertionheight
- \advance\mcscratchdimen -\totalinsertionheight
- \ifcase\multicolumnlinemethod \getnoflines\mcscratchdimen
- \or \getrawnoflines\mcscratchdimen
- \else \getrawnoflines\mcscratchdimen
+\unexpanded\def\page_mul_set_n_of_lines
+ {\settotalinsertionheight
+ \d_page_mul_temp\dimexpr
+ -\d_page_mul_offset*\plustwo
+ +\textheight
+ \ifdim\d_page_mul_preceding_height>\zeropoint -\d_page_mul_preceding_height \fi
+ -\totalinsertionheight
+ \relax
+ \ifcase\multicolumnlinemethod
+ \getnoflines \d_page_mul_temp \or
+ \getrawnoflines\d_page_mul_temp \else
+ \getrawnoflines\d_page_mul_temp
\fi
% added 30/7/2004
\ifnum\layoutlines>\zerocount \ifnum\noflines>\layoutlines
\noflines\layoutlines
\fi \fi
- \nofcolumnlines\noflines}
-
-\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
+ \c_page_mul_n_of_lines\noflines}
\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
+ \page_mul_set_n_of_lines
+ \d_page_mul_temp\nofcolumns\dimexpr
+ \c_page_mul_n_of_lines\openlineheight
+ +\multicolumnovershootratio\openlineheight % collect enough data
+ \relax
+ \global\vsize\d_page_mul_temp
+ \pagegoal \d_page_mul_temp} % let's do it only here
%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 \type {\b_page_mul_preceding}.
%D
%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.
+%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
+\setnewconstant\c_page_mul_routine_regular \zerocount
+\setnewconstant\c_page_mul_routine_intercept \plusone
+\setnewconstant\c_page_mul_routine_continue \plustwo
+\setnewconstant\c_page_mul_routine_balance \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
+ \page_mul_routine_intercept
\or
- \continuousmulticolumnsout
+ \page_mul_routine_continue
\or
- \balancedmulticolumnsout
+ \page_mul_routine_balance
\or
- \balancingerror
+ \page_mul_routine_error
\fi}
-\def\interceptmulticolumnsout
- {\global\setbox\precolumnbox\vbox
- {\page_otr_command_flush_top_insertions\unvbox\normalpagebox}}
+\def\page_mul_routine_intercept
+ {\global\setbox\b_page_mul_preceding\vbox
+ {\page_otr_command_flush_top_insertions
+ \unvbox\normalpagebox}}
-\def\beginmulticolumns
- {\par
- \flushnotes
- \xdef\precolumndepth{\the\prevdepth}%
- \begingroup
- % new
- \leftskip1\leftskip
- \rightskip1\rightskip
- \edef\colleftskip {\the\leftskip}%
- \edef\colrightskip{\the\rightskip}%
- \leftskip\zeropoint
- \rightskip\zeropoint
- %
- %\setcolumntextwidth\relax
- %\setcolumntextheight\relax
- \widowpenalty\zerocount % is gewoon beter
- \clubpenalty \zerocount % zeker bij grids
- \dopushcolumnfloats
- \dimen0\dimexpr\pagetotal+\parskip+\openlineheight\relax
- \ifdim\dimen0<\pagegoal
- \allowbreak
- \else
- \break % Sometimes fails
- \fi
- \appendtoks\topskip1\topskip\to\everybodyfont
- \the\everybodyfont % ugly here
- \saveinterlinespace % ugly here
- \initializecolumns\nofcolumns
- \hangafter\zerocount
- \hangindent\zeropoint
- \everypar\emptytoks
- \ifdim\pagetotal=\zeropoint \else
- \verticalstrut
- \vskip-\struttotal
- \fi
- \global\savedpagetotal\pagetotal
- \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
- \c_page_mul_routine\c_page_mul_routine_continuous
- \setcolumnfloats
- \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}%
- \checkbegincolumnfootnotes
- \page_otr_command_set_hsize
- \page_otr_command_set_vsize}
+\def\page_mul_routine_error
+ {\showmessage\m!columns3\empty
+ \page_otr_construct_and_shipout\unvbox\normalpagebox}
%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,
@@ -343,160 +350,150 @@
%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, e.g. when there is no
+%D Voiding box \type {\b_page_mul_preceding} 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 ! ! ! !
-
-\def\endmulticolumns
- {%\par
- \ifnum\multicolumnendsyncmethod=\plustwo
- \synchronizeoutput
- \else
- % don't combine these
- \vskip\lineheight
- \vskip-\lineheight % take footnotes into account
- \fi
- \doflushcolumnfloat % added recently
- %\doflushcolumnfloats % no, since it results in wrong top floats
- \flushnotes % before start of columns
- \par
- \ifbalancecolumns
- \ifnum\multicolumnendsyncmethod=\plusone
- \c_page_mul_routine\c_page_mul_routine_continuous
- \goodbreak
- \fi
- \c_page_mul_routine\c_page_mul_routine_balanced
- \else
- \goodbreak
- \fi
- % 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
- %
- \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
- \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 defined a macro for
%D them. Erasing \type{\everypar} is needed because we don't want anything
%D to interfere.
-\def\setmulticolumnsout
- {\everypar\emptytoks
+\unexpanded\def\page_mul_initialize_variables
+ {\reseteverypar
\dontcomplain
\settopskip
\setmaxdepth
- \topskip1\topskip
- \splittopskip\topskip
- \splitmaxdepth\maxdepth
- \boxmaxdepth\maxdepth % dangerous
- \emergencystretch\zeropoint\relax} % sometimes needed !
+ \topskip 1\topskip
+ \splittopskip \topskip
+ \splitmaxdepth \maxdepth
+ \boxmaxdepth \maxdepth % dangerous
+ \emergencystretch\zeropoint
+ \relax} % sometimes needed !
%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 to box \type {\b_page_mul_preceding}, 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 \type {\precolumnbox}
+%D One of the complications of flushing out the boxes is that \type {\b_page_mul_preceding}
%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 \type {\page_mul_routine_error}'s.
%D
%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
+\newdimen\maxcolumnheight
+\newdimen\maxcolumndepth
\newbox\columnpagebox
-\def\setmaxcolumndimensions
- {\let\maxcolumnheight\!!zeropoint
- \let\maxcolumndepth \!!zeropoint
- \dohandleallcolumns
- {\ifdim\ht\currentcolumnbox>\maxcolumnheight
- \edef\maxcolumnheight{\the\ht\currentcolumnbox}%
- \fi
- \ifdim\dp\currentcolumnbox>\maxcolumndepth
- \edef\maxcolumndepth{\the\dp\currentcolumnbox}%
- \fi}}
+\def\page_mul_calculate_column_result_dimensions
+ {\maxcolumnheight\zeropoint
+ \maxcolumndepth \zeropoint
+ \dohandleallcolumnscs\page_mul_calculate_column_result_dimensions_step}
+
+\def\page_mul_calculate_column_result_dimensions_step
+ {\ifdim\ht\currentcolumnbox>\maxcolumnheight
+ \maxcolumnheight\ht\currentcolumnbox
+ \fi
+ \ifdim\dp\currentcolumnbox>\maxcolumndepth
+ \maxcolumndepth\dp\currentcolumnbox
+ \fi}
\setnewconstant\multicolumntopflushmethod\plusone % 0: no correction, 1: correction when topstuff, 2: correction, 3: correction++
\setnewconstant\multicolumntopalignmethod\plustwo % 0: nothing, 1: force grid, 2: follow grid
-\def\flushprecolumnboxnogrid
- {\unvbox\precolumnbox}
-
-\def\flushprecolumnboxongrid
- {\scratchdimen\savedpagetotal
- \advance\scratchdimen -\ht\precolumnbox
- \advance\scratchdimen -\dp\precolumnbox
- \advance\scratchdimen -\topskip
- \box\precolumnbox
+\def\page_mul_flush_preceding_normal
+ {\unvbox\b_page_mul_preceding}
+
+\def\page_mul_flush_preceding_ongrid
+ {\scratchdimen\dimexpr
+ \savedpagetotal
+ -\d_page_mul_preceding_height
+ -\d_page_mul_preceding_depth
+ -\topskip
+ \relax
+ \box\b_page_mul_preceding
\kern\scratchdimen}
-\newconditional\someprecolumncontent
+\def\page_mul_flush_packaged_columns_continued
+ {\bgroup
+ \page_mul_flush_packaged_columns_indeed
+ \box\columnpagebox
+ \egroup}
-\def\flushcolumnedpage#1%
+\def\page_mul_flush_packaged_columns_balanced
{\bgroup
- \ifvoid\precolumnbox
- \setfalse\someprecolumncontent % will be set elsewhere
+ \page_mul_flush_packaged_columns_indeed
+ % messy correction, we need to rewrite this module (newcolumns)
+ \setbox\columnpagebox\vbox
+ {\offinterlineskip
+ \scratchdimen\ht\columnpagebox
+ \advance\scratchdimen\dp\columnpagebox % we probably lost that one already
+ \box\columnpagebox
+ \vskip-\scratchdimen}%
+ \scratchdimen\noflines\openlineheight
+ \advance\scratchdimen-\openstrutdepth
+ \ifgridsnapping
+ % quick hack (at least it works with itemize)
\else
- \settrue\someprecolumncontent
- \mkprocessboxcontents\precolumnbox
+ \advance\scratchdimen-\openlineheight
+ \advance\scratchdimen\topskip
+ \fi
+ \ht\columnpagebox\scratchdimen
+ \dp\columnpagebox\openstrutdepth
+ % end of mess
+ \box\columnpagebox
+ \egroup}
+
+\def\page_mul_flush_packaged_columns_indeed
+ {\ifvoid\b_page_mul_preceding
+ \setfalse\c_page_mul_preceding_present % will be set elsewhere
+ \else
+ \settrue\c_page_mul_preceding_present
+ \page_postprocessors_box\b_page_mul_preceding
\fi
\forgetall
- \setmulticolumnsout
- \setmaxcolumndimensions
+ \page_mul_initialize_variables
+ \page_mul_calculate_column_result_dimensions
+ \page_mul_postprocess_linenumbers
\dohandleallcolumns
- {\mkprocesscolumncontents\currentcolumnbox}%
+ {\page_postprocessors_column\currentcolumnbox}%
\dohandleallcolumns
{\page_marks_synchronize_column\plusone\nofcolumns\mofcolumns\currentcolumnbox}%
- \postprocesscolumns
+ \page_mul_postprocess_lines
+ \page_mul_postprocess_columns
\dohandleallcolumns
- {\global\setbox\currentcolumnbox\hbox to \localcolumnwidth
+ {\global\setbox\currentcolumnbox\hbox to \d_page_mul_used_width
{\box\currentcolumnbox}%
- \wd\currentcolumnbox\localcolumnwidth
+ \wd\currentcolumnbox\d_page_mul_used_width
\ifheightencolumns
- \ht\currentcolumnbox\fixedcolumnheight
+ \ht\currentcolumnbox\d_page_mul_forced_height
\fi}%
- \setmaxcolumndimensions
+ \page_mul_calculate_column_result_dimensions
\overlaycolumnfootnotes
\setbox\columnpagebox\vbox
- {\hbox to \finalcolumntextwidth
- {\hskip\colleftskip\relax % new, \relax needed
- \ifreversecolumns
- \@EA\dohandlerevcolumns
+ {\hbox to \makeupwidth
+ {\hskip\d_page_mul_leftskip\relax % new, \relax needed
+ \ifconditional\c_page_mul_reverse
+ \expandafter\dohandlerevcolumns
\else
- \@EA\dohandleallcolumns
+ \expandafter\dohandleallcolumns
\fi
{\finishcolumnbox
{\setbox\scratchbox\hbox
{\ifx\finishcolumnbox\relax\else\strut\fi
- \strut\box\currentcolumnbox}%
+ \box\currentcolumnbox}% hm, why strut
\anch_mark_column_box\scratchbox
\box\scratchbox}%
\hfil}%
\unskip
- \hskip\colrightskip}}% new
+ \hskip\d_page_mul_rightskip}}% new
\scratchdimen\zeropoint
\dohandleallcolumns
{\ifdim-\ht\currenttopcolumnbox<\scratchdimen
@@ -504,31 +501,31 @@
\fi
\global\setbox\currenttopcolumnbox\emptybox}%
\advance\scratchdimen \ht\columnpagebox
- \setbox\scratchbox\hbox to \columntextwidth
+ \setbox\scratchbox\hbox to \makeupwidth
{\vrule
- \!!width\zeropoint
- \!!height\scratchdimen
- \!!depth\dp\columnpagebox
- \dostepwiserecurse2\nofcolumns1{\hfil\betweencolumns}\hfil}%
+ \s!width\zeropoint
+ \s!height\scratchdimen
+ \s!depth\dp\columnpagebox
+ \dostepwiserecurse\plustwo\nofcolumns\plusone{\hfil\page_mul_between_columns}\hfil}%
\setbox\columnpagebox\hbox
{\box\columnpagebox
- \hskip-\columntextwidth
+ \hskip-\makeupwidth
\box\scratchbox}%
- \postprocesscolumnpagebox % new, acts upon \box\columnpagebox
- \ifconditional\someprecolumncontent
- \settrue\someprecolumncontent
+ \page_mul_postprocess_page
+ \ifconditional\c_page_mul_preceding_present
+ \settrue\c_page_mul_preceding_present
% next some incredible crappy code
\ifcase\multicolumntopalignmethod
- \flushprecolumnboxnogrid % not on grid
+ \page_mul_flush_preceding_normal % not on grid
\or
- \flushprecolumnboxongrid % force on grid
- \else\ifgridsnapping % somehow this junk fails in pascal
- \flushprecolumnboxongrid % obey grid settings, force on grid
+ \page_mul_flush_preceding_ongrid % force on grid
+ \else\ifgridsnapping
+ \page_mul_flush_preceding_ongrid % obey grid settings, force on grid
\else
- \flushprecolumnboxnogrid % ignore grid settings, not on grid
+ \page_mul_flush_preceding_normal % ignore grid settings, not on grid
\fi \fi
\fi
- \global\precolumnboxheight\zeropoint
+ \global\d_page_mul_preceding_height\zeropoint
\page_otr_command_set_vsize
\dosomebreak\nobreak % hm, only needed when topstuff
\ifgridsnapping
@@ -538,7 +535,7 @@
% when we run into it again
\or
% \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte
- \ifconditional\someprecolumncontent
+ \ifconditional\c_page_mul_preceding_present
% \scratchdimen\topskip
% \advance\scratchdimen -\openstrutheight
% \nointerlineskip
@@ -571,29 +568,7 @@
\dp\columnpagebox\zeropoint
\global\finalcolumnheights\ht\columnpagebox
\getnoflines\finalcolumnheights
- \global\finalcolumnlines\noflines
- \ifcase#1\else
- % messy correction, we need to rewrite this module (newcolumns)
- \setbox\columnpagebox\vbox
- {\offinterlineskip
- \scratchdimen\ht\columnpagebox
- \advance\scratchdimen\dp\columnpagebox % we probably lost that one already
- \box\columnpagebox
- \vskip-\scratchdimen}%
- \scratchdimen\noflines\openlineheight
- \advance\scratchdimen-\openstrutdepth
- \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
- \fi
- \box\columnpagebox
- \egroup}
+ \global\finalcolumnlines\noflines}
%D In case one didn't notice, finaly \type{\finishcolumnbox} is applied to
%D all boxes. One can use these hooks for special purposes.
@@ -637,51 +612,55 @@
%D
%D {\getbuffer}
%D
-%D This feature is implemented using the reshape macros
-%D presented in \type{supp-box}.
-
-\def\postprocesscolumns
- {\ifx\postprocesscolumnline\undefined \else
- \dohandleallcolumns
- {\global\setbox\currentcolumnbox\vtop
- {\beginofshapebox
- \unvbox\currentcolumnbox
- \unskip\unskip
- \endofshapebox
- \reshapebox
- {\dimen0\ht\shapebox
- \dimen2\dp\shapebox
- \setbox\shapebox\hbox to \hsize
- {\postprocesscolumnline\shapebox}%
- \ht\shapebox\dimen0
- \dp\shapebox\dimen2
- \box\shapebox}%
- \flushshapebox
- \everypar\emptytoks
- \parskip\zeropoint % = \forgetall
- \verticalstrut
- \vskip-\struttotal
- \vfil}}%
- \fi
- \ifx\postprocesscolumnbox\undefined \else
- \dohandleallcolumns
- {\global\setbox\currentcolumnbox\hbox
- {\postprocesscolumnbox\currentcolumnbox}}
- \fi}
-
-%D We default to doing nothing!
-
-\let\postprocesscolumnline =\undefined
-\let\postprocesscolumnbox =\undefined
-\let\postprocesscolumnpagebox=\relax
-
-%D \macros
-%D {reversecolumnstrue}
-%D
-%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 This feature is implemented using the reshape macros presented
+%D in \type{supp-box}.
+
+\ifdefined\page_postprocessors_column\else\let\page_postprocessors_column\relax\fi % operates on passed box
+\ifdefined\postprocesscolumnline \else\let\postprocesscolumnline \relax\fi % operates on passed box
+\ifdefined\postprocesscolumnbox \else\let\postprocesscolumnbox \relax\fi % operates on passed box
+\ifdefined\postprocesscolumnpagebox \else\let\postprocesscolumnpagebox \relax\fi % operates on passed box
+
+\def\page_mul_postprocess_linenumbers{\ifx\page_postprocessors_column\relax\else\page_mul_postprocess_linenumbers_indeed\fi}
+\def\page_mul_postprocess_lines {\ifx\postprocesscolumnline \relax\else\page_mul_postprocess_lines_indeed \fi}
+\def\page_mul_postprocess_columns {\ifx\postprocesscolumnbox \relax\else\page_mul_postprocess_columns_indeed \fi}
+\def\page_mul_postprocess_page {\ifx\postprocesscolumnpagebox \relax\else\page_mul_postprocess_page_indeed \fi}
+
+\def\page_mul_postprocess_linenumbers_indeed
+ {\dohandleallcolumns{\page_postprocessors_column\currentcolumnbox}}
+
+\def\page_mul_postprocess_lines_indeed
+ {\dohandleallcolumnscs\page_mul_postprocess_lines_step}
+
+\def\page_mul_postprocess_lines_step % TODO: use lua solution instead
+ {\global\setbox\currentcolumnbox\vtop
+ {\beginofshapebox
+ \unvbox\currentcolumnbox
+ \unskip\unskip
+ \endofshapebox
+ \reshapebox
+ {\scratchheight\ht\shapebox
+ \scratchdepth \dp\shapebox
+ \setbox\shapebox\hbox to \hsize
+ {\postprocesscolumnline\shapebox}%
+ \ht\shapebox\scratchheight
+ \dp\shapebox\scratchdepth
+ \box\shapebox}%
+ \flushshapebox
+ \reseteverypar
+ \parskip\zeropoint % = \forgetall
+ \verticalstrut
+ \vskip-\struttotal
+ \vfil}}
+
+\def\page_mul_postprocess_columns_indeed
+ {\dohandleallcolumnscs\page_mul_postprocess_columns_step}
+
+\def\page_mul_postprocess_columns_step
+ {\global\setbox\currentcolumnbox\hbox
+ {\postprocesscolumnbox\currentcolumnbox}}
+
+\def\page_mul_postprocess_page_indeed
+ {\postprocesscolumnpagebox\columnpagebox}
%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
@@ -691,46 +670,48 @@
%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%
+\newdimen\d_page_mul_split_height_used
+\newdimen\d_page_mul_split_height_max
+
+\def\page_mul_split_column#1#2#3#4% copy or box
{\bgroup
\ifdim\ht#4>\zeropoint
- \dimen0\dimen#3\relax
- \dimen2\dimen0
- \advance\dimen0 -\ht#4%
- \columnfootnotecorrection{#1}{\dimen0}%
- \setbox0\vsplit#2 to \dimen0
- \global\setbox#1\vbox to \dimen2
+ \d_page_mul_split_height_used#3\relax
+ \d_page_mul_split_height_max\d_page_mul_split_height_used
+ \advance\d_page_mul_split_height_used -\ht#4%
+ \columnfootnotecorrection{#1}\d_page_mul_split_height_used
+ \setbox\scratchbox\vsplit#2 to \d_page_mul_split_height_used
+ \global\setbox#1\vbox to \d_page_mul_split_height_max
{\ifgridsnapping
- \dimen0-\openstrutheight
- \advance\dimen0 \topskip
- \vskip\dimen0\copy#4\vskip-\dimen0
+ \scratchdimen\dimexpr\topskip-\openstrutheight\relax
+ \vskip\scratchdimen
+ \copy#4%
+ \vskip-\scratchdimen
\else
\unvcopy#4%
\fi
- \fuzzysnappedbox\unvbox0
+ \fuzzysnappedbox\unvbox\scratchbox
\fakecolumnfootnotes{#1}}%
+ \else\ifcase\c_strc_notes_page_location
+ \global\setbox#1\vsplit#2 to #3%
+ \global\setbox#1\vbox
+ {\fuzzysnappedbox\unvbox{#1}}% % or \box ?
\else
- \ifcase\c_strc_notes_page_location
- \global\setbox#1\vsplit#2 to \dimen#3%
- \global\setbox#1\vbox
- {\fuzzysnappedbox\unvbox{#1}}% % or \box ?
- \else
- \columnfootnotecorrection{#1}{\dimen#3}%
- \setbox0\vsplit#2 to \dimen#3%
- \global\setbox#1\vbox to \dimen#3%
- {\fuzzysnappedbox\unvbox0
- \fakecolumnfootnotes{#1}}%
- \fi
- \fi
+ \columnfootnotecorrection{#1}{#3}%
+ \setbox\scratchbox\vsplit#2 to #3%
+ \global\setbox#1\vbox to #3%
+ {\fuzzysnappedbox\unvbox\scratchbox
+ \fakecolumnfootnotes{#1}}%
+ \fi \fi
\egroup}
-\def\splitcurrentcolumn from \box#1to \dimen#2%
- {\splitcolumn\currentcolumnbox from \box#1 to \dimen#2 top \box\currenttopcolumnbox}
+\def\page_mul_split_current_column#1#2%
+ {\page_mul_split_column\currentcolumnbox{#1}{#2}\currenttopcolumnbox}
-\def\splitfirstcolumn from \box#1to \dimen#2%
- {\splitcolumn\firstcolumnbox from \box#1 to \dimen#2 top \box\firsttopcolumnbox}
+\def\page_mul_split_first_column#1#2%
+ {\page_mul_split_column\firstcolumnbox{#1}{#2}\firsttopcolumnbox}
-\def\splitlastcolumn from \box#1to \dimen#2%
+\def\page_mul_split_last_column#1#2%
{\global\setbox\lastcolumnbox\vbox
{\unvcopy\lasttopcolumnbox
\fuzzysnappedbox\unvbox{#1}%
@@ -738,128 +719,130 @@
%D NEW: still to be documented.
-\def\fakecolumnfootnotes#1%
- {\relax
- \ifcase\c_strc_notes_page_location\else
- \ifnum#1=\lastcolumnbox
- \fakenotes
- \fi
- \fi}
-
-\def\columnfootnotecorrection#1#2%
- {\relax
- \ifcase\c_strc_notes_page_location
- % page notes
- \or
- \ifnum#1=\firstcolumnbox\relax
- \calculatetotalclevernoteheight
- \advance#2 -\totalnoteheight
- \fi
- \else
- \ifnum#1=\lastcolumnbox\relax
- \calculatetotalclevernoteheight
- \advance#2 -\totalnoteheight
- \fi
- \fi}
-
-\def\overlaycolumnfootnotes
- {\relax
- \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}
-
-\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\fakecolumnfootnotes#1%
+ {\relax
+ \ifcase\c_strc_notes_page_location\else
+ \ifnum#1=\lastcolumnbox
+ \fakenotes
+ \fi
+ \fi}
+
+ \def\columnfootnotecorrection#1#2%
+ {\relax
+ \ifcase\c_strc_notes_page_location
+ % page notes
+ \or
+ \ifnum#1=\firstcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \else
+ \ifnum#1=\lastcolumnbox\relax
+ \calculatetotalclevernoteheight
+ \advance#2 -\totalnoteheight
+ \fi
+ \fi}
+
+ \def\overlaycolumnfootnotes
+ {\relax
+ \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}
+
+ \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
+ \page_mul_set_n_of_lines
+ \advance\c_page_mul_n_of_lines \minustwo
+ \scratchdimen\dimexpr\c_page_mul_n_of_lines\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}
+ \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 \page_mul_set_n_of_lines
+ \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 {\page_mul_flush_floats} 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
+\def\page_mul_routine_continue
{\bgroup
\forgetall
- \setmulticolumnsout
-% \dimen0=\columntextheight
-% \advance\dimen0 -\precolumnboxheight
-% \settotalinsertionheight
-% \advance\dimen0 -\totalinsertionheight
-% \ifgridsnapping % evt altijd, nog testen
-% \getnoflines{\dimen0}
-% \dimen0=\noflines\openlineheight
-% \fi
- \getmulticolumnlines
- \dimen0=\nofcolumnlines\openlineheight
+ \page_mul_initialize_variables
+ % \dimen0=\makeupheight
+ % \advance\dimen0 -\d_page_mul_preceding_height
+ % \settotalinsertionheight
+ % \advance\dimen0 -\totalinsertionheight
+ % \ifgridsnapping % evt altijd, nog testen
+ % \getnoflines{\dimen0}
+ % \dimen0=\noflines\openlineheight
+ % \fi
+ \page_mul_set_n_of_lines
+ \d_page_mul_balance_target\c_page_mul_n_of_lines\openlineheight
+ \ifconditional\c_page_mul_trace
+ \writestatus\m!columns{continue: lines=\the\c_page_mul_n_of_lines, target=\the\d_page_mul_balance_target, textheight=\the\textheight}%
+ \fi
\dohandleallcolumns
- {\splitcurrentcolumn from \box\normalpagebox to \dimen0}%
- \setbox\restofpage\vbox{\unvbox\normalpagebox}%
+ {\page_mul_split_current_column\normalpagebox\d_page_mul_balance_target}%
+ \setbox\b_page_mul_preceding_rest_of_page\vbox{\unvbox\normalpagebox}%
\ifinheritcolumns
\ifcase\bottomraggednessmode
% 0 = ragged
\dohandleallcolumns
{\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
- {\dimen0\dp\currentcolumnbox
+ {\scratchdepth\dp\currentcolumnbox
\unvbox\currentcolumnbox
- \vskip-\dimen0
- \vskip\openstrutdepth % \strutdp
+ \vskip\dimexpr\openstrutdepth-\scratchdepth\relax
\prevdepth\openstrutdepth % \strutdp
\vfill}}%
\strc_notes_check_if_bottom_present
- \ifconditional\c_notes_bottom_present \else
- \dimen0\ht\firstcolumnbox
- \fi
+ %\ifconditional\c_notes_bottom_present \else
+ % \dimen0\ht\firstcolumnbox % ??
+ %\fi
\or
% 1 = normal
- \advance\dimen0 \maxdepth
+ \advance\d_page_mul_balance_target\maxdepth
\dohandleallcolumns
- {\global\setbox\currentcolumnbox\vbox to \dimen0
+ {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
{\unvbox\currentcolumnbox}}%
\or
% 2 = baseline
@@ -867,7 +850,7 @@
\fi
\else
\dohandleallcolumns
- {\global\setbox\currentcolumnbox\vbox to \dimen0
+ {\global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
{\ifstretchcolumns
\unvbox\currentcolumnbox
\else
@@ -875,14 +858,14 @@
\vfill
\fi}}%
\dohandleallcolumns
- {\ht\currentcolumnbox\dimen0}% redundant
+ {\ht\currentcolumnbox\d_page_mul_balance_target}% redundant
\fi
- \setbox\precolumnbox\vbox{\flushcolumnedpage\zerocount}%
- \page_otr_construct_and_shipout\box\precolumnbox
+ \setbox\b_page_mul_preceding\vbox{\page_mul_flush_packaged_columns_continued}%
+ \page_otr_construct_and_shipout\box\b_page_mul_preceding
\page_otr_command_set_hsize
\page_otr_command_set_vsize
- \flushcolumnfloats
- \unvbox\restofpage
+ \page_mul_flush_floats
+ \unvbox\b_page_mul_preceding_rest_of_page
% \penalty\outputpenalty % gaat gruwelijk mis in opsommingen
\egroup}
@@ -892,161 +875,184 @@
%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
+\newbox \b_page_mul_balance_content
+\newbox \b_page_mul_balance_first_column
+\newbox \b_page_mul_balance_column
+\newconstant \c_page_mul_balance_tries_max
+\newcount \c_page_mul_balance_tries
+\newdimen \d_page_mul_balance_target
+\newdimen \d_page_mul_balance_target_less
+\newdimen \d_page_mul_balance_natural_height
+\newdimen \d_page_mul_balance_regular_height
+\newdimen \d_page_mul_balance_step
+\newdimen \d_page_mul_balance_fuzzyness
+\newdimen \d_page_mul_balance_threshold
+\newconditional\c_page_mul_balance_possible
+
+\c_page_mul_balance_tries_max 250 % 100 is too small when floats are involved
+
+\def\page_mul_routine_balance
{\bgroup
- \setmulticolumnsout
+ \page_mul_initialize_variables
\widowpenalty\zerocount
- \setbox0\vbox{\unvbox\normalpagebox}%
- \ifdim\ht0>\openlineheight % at least one line
- \ifnum\minbalancetoplines<2 % balance anyway
- \donetrue
+ \setbox\b_page_mul_balance_content\vbox{\unvbox\normalpagebox}%
+ \ifdim\ht\b_page_mul_balance_content>\openlineheight % at least one line
+ \ifnum\c_page_mul_balance_minimum<\plustwo % balance anyway
+ \settrue\c_page_mul_balance_possible
\else % check criterium to available lines
- \getnoflines{\ht0}%
+ \getnoflines{\ht\b_page_mul_balance_content}%
\divide\noflines \nofcolumns \relax
- \ifnum\noflines<\minbalancetoplines \relax
- % let's play safe
- \ifdim\dimexpr\ht0+\ht\firsttopcolumnbox+\openlineheight\relax>\columntextheight
- \donetrue % column exceeding text height
+ \ifnum\noflines<\c_page_mul_balance_minimum \relax
+ \ifdim\dimexpr\ht\b_page_mul_balance_content+\ht\firsttopcolumnbox+\openlineheight\relax>\makeupheight
+ \settrue\c_page_mul_balance_possible % column exceeding text height
\else
- \donefalse % it seems to fit
+ \setfalse\c_page_mul_balance_possible % it seems to fit
\fi
- \else % balance indeed
- \donetrue
+ \else
+ \settrue\c_page_mul_balance_possible % balance indeed
\fi
\fi
- \else % balancing does not make sense
- \donefalse
+ \else
+ \setfalse\c_page_mul_balance_possible % balancing does not make sense
\fi
- \ifdone % start balancing, was: \ifdim\ht0>\openlineheight
- \dimen0\ht0
- \advance\dimen0 \topskip
- \advance\dimen0 -\baselineskip
- \dohandleallcolumns
- {\advance\dimen0 \ht\currenttopcolumnbox}%
- \divide\dimen0 \nofcolumns
- \vbadness\plustenthousand
- \count255=\zerocount
- \bgroup
- \ifgridsnapping
- \dimen2\lineheight
- \else
- \dimen2=\onepoint % RUBISH
- \dimen2=\spacingfactor\dimen2
- \fi
- \doloop
- {\advance\count255 \plusone
- \global\setbox\restofpage\copy0\relax
- \splitfirstcolumn from \box\restofpage to \dimen0
- \dohandlemidcolumns
- {\splitcurrentcolumn from \box\restofpage to \dimen0}%
- \splitlastcolumn from \box\restofpage to \dimen0
- \setbox2\vbox{\unvcopy\firstcolumnbox}%
- \dimen4\zeropoint
- \dohandleallcolumns
- {\setbox4\vbox
- {\unvcopy\currentcolumnbox
- %rather new, test this on pdftex-z.tex
- \unpenalty\unskip\unpenalty\unskip}% maybe better in main splitter
- %\writestatus{balance}{\the\currentcolumnbox: \the\ht4}%
-% \dimen6\ht4 \ifdim\dimen6>\dimen4 \dimen4=\dimen6 \fi}%
- \ifdim\ht4>\dimen4 \dimen4=\ht4 \fi}%
- \advance\dimen4 -.0005pt % get rid of accurracy problem, pretty new
- \ifnum\count255>\multicolumnsbalancemax\relax
- \exitloop
- \else\ifdim\dimen4>\ht2
- \advance\dimen0 \dimen2\relax
- \else
- \exitloop
- \fi\fi}%
- \dohandleallcolumns
- {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}% NIEUW
- \ifnum\count255>\multicolumnsbalancemax\relax
- \showmessage\m!columns7\empty
- \else
- \showmessage\m!columns8{\the\count255\space}%
- \fi
- \egroup
+ \ifconditional\c_page_mul_balance_possible % start balancing, was: \ifdim\ht\b_page_mul_balance_content>\openlineheight
+ \page_mul_balance_try_one
\ifinheritcolumns
- % We cannot assume that the first column is the tallest, if
- % only because we may have an aborted balance (one line in the
- % first column and a graphic in the second one).
- %
- % \dimen0\ht\firstcolumnbox
- % \dimen2\ht\firstcolumnbox
- %
- \dimen0=\zeropoint
- \dohandleallcolumns
- {\ifdim\ht\currentcolumnbox>\dimen0
- \dimen0=\ht\currentcolumnbox
- \fi}%
- \dimen2\dimen0
- % so far
- \advance\dimen2 -\openlineheight
- \dohandleallcolumns
- {\dimen4\ht\currentcolumnbox
- \dimen6=10\openlineheight % funny value
- \global\setbox\currentcolumnbox\vbox to \dimen0
- {\unvbox\currentcolumnbox
- \ifdim\dimen4>\dimen6
- \ifdim\dimen4<\dimen0
- \ifdim\dimen4>\dimen2
- \vskip\zeropoint % !!
- \else
- \vskip\openlineheight
- \vfill
- \fi
- \else
- \vskip\zeropoint
- \fi
- \else
- \vskip\openlineheight
- \vfill
- \fi}}%
+ \page_mul_balance_try_two
\else
- \bgroup
- \ifstretchcolumns
- \dimen0\ht\firstcolumnbox
- \dimen2=\bottomtolerance\ht\firstcolumnbox
- \setbox0\vbox{\unvcopy\lastcolumnbox}%
- \advance\dimen0 -\ht0\relax
- \advance\dimen0 -\dp0\relax
- \ifdim\dimen0>\openlineheight\relax
- \ifdim\dimen0>\dimen2\relax
- % \stretchcolumnsfalse % beter goed slecht dan slecht goed
- \showmessage\m!columns9\empty
- \fi
- \fi
- \fi
- \dohandleallcolumns
- {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
- {\ifstretchcolumns
- \unvbox\currentcolumnbox
- \else
- \box\currentcolumnbox
- \vfill
- \fi}}%
- \egroup
+ \page_mul_balance_try_three
\fi
\else
% a one liner is not properly handled here, so best rewrite the text then
\showmessage\m!columns{10}\empty
- \global\setbox\firstcolumnbox\vbox{\unvbox0}%
+ \global\setbox\firstcolumnbox\vbox{\unvbox\b_page_mul_balance_content}%
\fi
\c_page_mul_routine\c_page_mul_routine_error
\baselinebottom % forces depth in separation rule
- \flushcolumnedpage\plusone
- \multicolumnseject
+ \page_mul_flush_packaged_columns_balanced
+ \page_mul_eject_page
\egroup}
-\def\multicolumnseject
+\def\page_mul_eject_page
{%\ifdim\pagetotal>\textheight
% \page_otr_trigger_output_routine % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point)
%\else
\allowbreak
}%\fi}
+\def\page_mul_balance_try_one
+ {\d_page_mul_balance_target\dimexpr\ht\b_page_mul_balance_content+\topskip-\baselineskip\relax
+ \dohandleallcolumns
+ {\advance\d_page_mul_balance_target \ht\currenttopcolumnbox}%
+ \divide\d_page_mul_balance_target \nofcolumns
+ \vbadness\plustenthousand
+ \c_page_mul_balance_tries\zerocount
+ \bgroup
+ \ifgridsnapping
+ \d_page_mul_balance_step\lineheight
+ \else
+ \d_page_mul_balance_step\spacingfactor\onepoint % rubish
+ \fi
+ \doloop\page_mul_balance_try_one_attempt
+ \dohandleallcolumns
+ {\global\setbox\currentcolumnbox\vbox{\unvcopy\currentcolumnbox}}%
+ \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax
+ \showmessage\m!columns7\empty
+ \else
+ \showmessage\m!columns8{\the\c_page_mul_balance_tries\space}%
+ \fi
+ \egroup}
+
+\def\page_mul_balance_try_one_attempt
+ {\advance\c_page_mul_balance_tries \plusone
+ \global\setbox\b_page_mul_preceding_rest_of_page\copy\b_page_mul_balance_content\relax
+ \page_mul_split_first_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target
+ \dohandlemidcolumns
+ {\page_mul_split_current_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target}%
+ \page_mul_split_last_column\b_page_mul_preceding_rest_of_page\d_page_mul_balance_target
+ \setbox\b_page_mul_balance_first_column\vbox{\unvcopy\firstcolumnbox}%
+ \d_page_mul_balance_natural_height\zeropoint
+ \dohandleallcolumns\page_mul_balance_try_one_attempt_step
+ \advance\d_page_mul_balance_natural_height -.0005pt % (33sp) get rid of accurracy problem, pretty new
+ \ifnum\c_page_mul_balance_tries>\c_page_mul_balance_tries_max\relax
+ \exitloop
+ \else\ifdim\d_page_mul_balance_natural_height>\ht\b_page_mul_balance_first_column
+ \advance\d_page_mul_balance_target \d_page_mul_balance_step\relax
+ \else
+ \exitloop
+ \fi\fi}
+
+\def\page_mul_balance_try_one_attempt_step
+ {\setbox\b_page_mul_balance_column\vbox
+ {\unvcopy\currentcolumnbox
+ \unpenalty
+ \unskip
+ \unpenalty
+ \unskip}% maybe better in main splitter
+ \ifdim\ht\b_page_mul_balance_column>\d_page_mul_balance_natural_height
+ \d_page_mul_balance_natural_height\ht\b_page_mul_balance_column
+ \fi}
+
+% We cannot assume that the first column is the tallest, if only because we may
+% have an aborted balance (one line in the first column and a graphic in the
+% second one).
+
+\def\page_mul_balance_try_two
+ {\d_page_mul_balance_target\zeropoint
+ \dohandleallcolumns
+ {\ifdim\ht\currentcolumnbox>\d_page_mul_balance_target
+ \d_page_mul_balance_target\ht\currentcolumnbox
+ \fi}%
+ \d_page_mul_balance_target_less\dimexpr\d_page_mul_balance_target-\openlineheight\relax
+ \dohandleallcolumnscs\page_mul_balance_try_two_step}
+
+\def\page_mul_balance_try_two_step
+ {\d_page_mul_balance_regular_height\ht\currentcolumnbox
+ \d_page_mul_balance_threshold\plusten\openlineheight % funny value
+ \global\setbox\currentcolumnbox\vbox to \d_page_mul_balance_target
+ {\unvbox\currentcolumnbox
+ \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_threshold
+ \ifdim\d_page_mul_balance_regular_height<\d_page_mul_balance_target
+ \ifdim\d_page_mul_balance_regular_height>\d_page_mul_balance_target_less
+ \vskip\zeropoint % !!
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi
+ \else
+ \vskip\zeropoint
+ \fi
+ \else
+ \vskip\openlineheight
+ \vfill
+ \fi}}
+
+\def\page_mul_balance_try_three
+ {\bgroup
+ \ifstretchcolumns
+ \d_page_mul_balance_target\ht\firstcolumnbox
+ \d_page_mul_balance_fuzzyness\bottomtolerance\ht\firstcolumnbox
+ \setbox\b_page_mul_balance_content\vbox{\unvcopy\lastcolumnbox}%
+ \advance\d_page_mul_balance_target-\htdp\b_page_mul_balance_content\relax
+ \ifdim\d_page_mul_balance_target>\openlineheight\relax
+ \ifdim\d_page_mul_balance_target>\d_page_mul_balance_fuzzyness\relax
+ % \stretchcolumnsfalse % beter good bad than bad good
+ \showmessage\m!columns9\empty
+ \fi
+ \fi
+ \fi
+ \dohandleallcolumnscs\page_mul_balance_try_three_step
+ \egroup}
+
+\def\page_mul_balance_try_three_step
+ {\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
+ {\ifstretchcolumns
+ \unvbox\currentcolumnbox
+ \else
+ \box\currentcolumnbox
+ \vfill
+ \fi}}
+
%D The multicolumn mechanism is incorporated in a \CONTEXT\ interface,
%D which acts like:
%D
@@ -1084,23 +1090,26 @@
%D
%D When all those floats are flushed, we switch to the local flushing routine.
-\def\dopushcolumnfloats
- {\ifsomefloatwaiting
- \showmessage\m!columns6{\the\savednoffloats}%
- \global\setbox\savedfloatlist\box\floatlist
- \xdef\dopopcolumnfloats
- {\global\savednoffloats\the\savednoffloats
- \global\setbox\floatlist\box\savedfloatlist
- \global\noexpand\somefloatwaitingtrue}%
- \global\savednoffloats\zerocount
- \global\somefloatwaitingfalse
- \else
- \global\let\dopopcolumnfloats\relax
- \fi}
-
-\let\dopopcolumnfloats\relax
+% \newbox \floatlist
+% \newbox \savedfloatlist
+%
+% \def\page_floats_column_push_saved
+% {\ifconditional\c_page_floats_some_waiting
+% \showmessage\m!columns6{\the\savednoffloats}%
+% \global\setbox\savedfloatlist\box\floatlist
+% \xdef\page_floats_column_pop_saved
+% {\global\savednoffloats\the\savednoffloats
+% \global\setbox\floatlist\box\savedfloatlist
+% \global\noexpand\settrue\c_page_floats_some_waiting}%
+% \global\savednoffloats\zerocount
+% \global\setfalse\c_page_floats_some_waiting
+% \else
+% \global\let\page_floats_column_pop_saved\relax
+% \fi}
+%
+% \let\page_floats_column_pop_saved\relax
-% \def\setcolumnfloats % messy as it adapts everypar
+% \def\page_mul_initialize_floats % messy as it adapts everypar
% {\xdef\globalsavednoffloats{\the\savednoffloats}%
% \ifnum\globalsavednoffloats>\zerocount
% \setglobalcolumnfloats % hm, we always push so this never happens
@@ -1108,66 +1117,66 @@
% \setlocalcolumnfloats
% \fi}
-\def\setcolumnfloats % messy as it adapts everypar, we need to adapt this
- {\setlocalcolumnfloats}
-
-\newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now)
+ \def\page_mul_initialize_floats % messy as it adapts everypar, we need to adapt this
+ {\setlocalcolumnfloats}
-\unexpanded\def\page_mul_command_flush_floats
- {\ifconditional\onlylocalcolumnfloats
- \doflushcolumnfloats
- \else
- \page_one_command_flush_floats
- \fi}
+ \newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now)
+ \newtoks \everylocalcolumnfloatspar
-\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
-
-\everylocalcolumnfloatspar
- {\flushnotes
- \flushcolumnfloat
- % \flushmargincontents
- \checkindentation}
+ \unexpanded\def\page_mul_command_flush_floats
+ {\ifconditional\onlylocalcolumnfloats
+ \doflushcolumnfloats
+ \else
+ \page_one_command_flush_floats
+ \fi}
-\def\setlocalcolumnfloats
- {\settrue\onlylocalcolumnfloats
- \everypar\everylocalcolumnfloatspar
- \let\flushcolumnfloat\doflushcolumnfloat
- \let\flushcolumnfloats\doflushcolumnfloats}
+ \unexpanded\def\page_mul_command_check_if_float_fits
+ {\ifconditional\onlylocalcolumnfloats
+ \docolumnroomfloat
+ \fi}
-\def\setglobalcolumnfloats
- {\setfalse\onlylocalcolumnfloats
- \everypar\emptytoks
- \let\flushcolumnfloat\relax
- \let\flushcolumnfloats\noflushcolumnfloats}
+ \unexpanded\def\page_mul_command_flush_saved_floats
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_saved_floats
+ \fi}
-\def\noflushcolumnfloats
- {\bgroup
- \xdef\localsavednoffloats{\the\savednoffloats}%
- \global\savednoffloats\globalsavednoffloats
- \page_otr_command_flush_top_insertions
- \xdef\globalsavenoffloats{\the\savednoffloats}%
- \ifnum\globalsavednoffloats=\zerocount
- \setlocalcolumnfloats
- \fi
- \global\savednoffloats\localsavednoffloats
- \egroup}
+ \unexpanded\def\page_mul_command_flush_top_insertions
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_top_insertions
+ \fi}
+
+ \appendtoks
+ \flushnotes
+ \page_mul_flush_float
+ %\flushmargincontents
+ \checkindentation
+ \to \everylocalcolumnfloatspar
+
+ \def\setlocalcolumnfloats
+ {\settrue\onlylocalcolumnfloats
+ \everypar\everylocalcolumnfloatspar
+ \let\page_mul_flush_float\doflushcolumnfloat
+ \let\page_mul_flush_floats\doflushcolumnfloats}
+
+ \def\setglobalcolumnfloats
+ {\setfalse\onlylocalcolumnfloats
+ \reseteverypar
+ \let\page_mul_flush_float\relax
+ \let\page_mul_flush_floats\noflushcolumnfloats}
+
+ \def\noflushcolumnfloats
+ {\bgroup
+ \xdef\localsavednoffloats{\the\savednoffloats}%
+ \global\savednoffloats\globalsavednoffloats
+ \page_otr_command_flush_top_insertions
+ \xdef\globalsavenoffloats{\the\savednoffloats}%
+ \ifnum\globalsavednoffloats=\zerocount
+ \setlocalcolumnfloats
+ \fi
+ \global\savednoffloats\localsavednoffloats
+ \egroup}
%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
@@ -1176,124 +1185,124 @@
%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
- \dimen2=\zeropoint
- \count255=\zerocount
- \dimen8=\columntextheight
- \advance\dimen8 -\precolumnboxheight
- \def\dogetcolumnstatus
- {\advance\count255 \plusone
- \advance\dimen2 \ht\currenttopcolumnbox
- \advance\dimen2 \dp\currenttopcolumnbox
- \dimen4\dimen2
- \advance\dimen4 \dimen0
- \dimen6=\count255\dimen8
- \ifdim\dimen4>\dimen6
- \else
- \let\dogetcolumnstatus\relax
- \fi}%
- \dohandleallcolumns{\dogetcolumnstatus}%
- \ifnum\count255=0 \count255=1 \fi
- #1=\count255
- #2=\dimen4
- #3=\dimen6 }
-
-\def\getinsertionheight
- {\ifdim\pagegoal<\maxdimen
- \bgroup
- \dimen0=\columntextheight
- \advance\dimen0 -\pagegoal
- \xdef\insertionheight{\the\dimen0}%
- \egroup
- \else
- \global\let\insertionheight\zeropoint
- \fi}
-
-\def\docolumnroomfloat
- {\ifpostponecolumnfloats
- \global\roomforfloatfalse
- \else\ifnofloatpermitted
- \global\roomforfloatfalse
- \else
- \bgroup
- \getcolumnstatus\column\count255\total\dimen0\goal\dimen2\\%
- \dofloatsgetinfo\s!text
- \setbox\scratchbox\vbox % tricky met objecten ?
- {\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
- \global\roomforfloatfalse
- \else
- \global\roomforfloattrue
- \fi
- \ifdim\floatwidth>\hsize
- \showmessage\m!columns{11}\empty
- \global\roomforfloatfalse
- \fi
- \egroup
- \fi\fi}
+ \def\getcolumnstatus#1#2#3%
+ {\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi
+ \dimen2=\zeropoint
+ \count255=\zerocount
+ \dimen8=\makeupheight
+ \advance\dimen8 -\d_page_mul_preceding_height
+ \def\dogetcolumnstatus
+ {\advance\count255 \plusone
+ \advance\dimen2 \ht\currenttopcolumnbox
+ \advance\dimen2 \dp\currenttopcolumnbox
+ \dimen4\dimen2
+ \advance\dimen4 \dimen0
+ \dimen6=\count255\dimen8
+ \ifdim\dimen4>\dimen6
+ \else
+ \let\dogetcolumnstatus\relax
+ \fi}%
+ \dohandleallcolumns{\dogetcolumnstatus}%
+ \ifnum\count255=0 \count255=1 \fi
+ #1=\count255
+ #2=\dimen4
+ #3=\dimen6 }
+
+ \def\getinsertionheight
+ {\ifdim\pagegoal<\maxdimen
+ \bgroup
+ \dimen0=\makeupheight
+ \advance\dimen0 -\pagegoal
+ \xdef\insertionheight{\the\dimen0}%
+ \egroup
+ \else
+ \global\let\insertionheight\zeropoint
+ \fi}
+
+ \def\docolumnroomfloat
+ {\ifpostponecolumnfloats
+ \global\setfalse\c_page_floats_room
+ \else\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
+ \else
+ \bgroup
+ \getcolumnstatus{\count255}{\dimen0}{\dimen2}%
+ \page_floats_get_info\s!text
+ \setbox\scratchbox\vbox % tricky met objecten ?
+ {\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
+ \global\setfalse\c_page_floats_room
+ \else
+ \global\settrue\c_page_floats_room
+ \fi
+ \ifdim\floatwidth>\hsize
+ \showmessage\m!columns{11}\empty
+ \global\setfalse\c_page_floats_room
+ \fi
+ \egroup
+ \fi\fi}
%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\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%
+ \newif\ifflushingcolumnfloats \flushingcolumnfloatstrue
+
+ \def\doflushcolumnfloat
+ {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifconditional\c_page_floats_some_waiting
+ \doflushcolumnfloatindeed
+ \fi\fi\fi}
+
+ \def\doflushcolumnfloatindeed
+ {\bgroup
+ \forgetall
+ \let\doflushcolumnfloat\relax
+ \getcolumnstatus{\mofcolumns}{\dimen0}{\dimen2}%
+ \ifdim\dimen0>\zeropoint
+ \page_floats_get_info\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
+ \page_floats_flush\s!text\plusone
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox{\box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \dimen4=\htdp\currenttopcolumnbox
+ \global\advance\vsize -\dimen4
+ \advance\dimen4 -\pagegoal
+ \pagegoal-\dimen4
+ \showmessage\m!columns{12}a%
+ \else
+ \showmessage\m!columns{12}b%
+ \fi
+ \else
+ \showmessage\m!columns{12}c%
+ \fi
\else
- \showmessage\m!columns{12}b%
+ \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
+ \page_floats_flush\s!text\plusone
+ \page_otr_command_flush_float_box
+ \blank[\rootfloatparameter\c!spaceafter]
\fi
- \else
- \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
- \fi
- \egroup}
+ \egroup}
%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
@@ -1308,96 +1317,96 @@
%D When handling lots of (small) floats spacing can get worse because of
%D lining out the columns.
-\def\doflushcolumnfloats
- {\ifpostponecolumnfloats\else
- \bgroup
- \forgetall
- \ifsomefloatwaiting
- \dimen8\zeropoint
- \dimen4\zeropoint
- \count0\zerocount % count0 can be used local
- \count2\nofcolumns % count2 can be used local
- \dohandleallcolumns
- {\ifnum\count0>\zerocount % the wide one's reserved space
- \global\setbox\currenttopcolumnbox\vbox
- {\snaptogrid\vbox
- {\copy\currenttopcolumnbox
- \hbox{\vphantom{\vskip\floatheight}}}% known from previous
- \whitespace % nodig ?
- \blank[\rootfloatparameter\c!spaceafter]}%
- \else
- \dofloatsgetinfo\s!text
- \ifdim\floatwidth>\hsize
- \dimen0\dimexpr\floatwidth+\intercolumnwidth+.5pt\relax
- \dimen2\dimexpr\hsize +\intercolumnwidth+.5pt\relax
- \divide\dimen0 \dimen2
- \count0\dimen0
- \advance\count0 \plusone
- \ifnum\count0>\count2
- \count0\zerocount
+ \def\doflushcolumnfloats
+ {\ifpostponecolumnfloats\else
+ \bgroup
+ \forgetall
+ \ifconditional\c_page_floats_some_waiting
+ \dimen8\zeropoint
+ \dimen4\zeropoint
+ \count0\zerocount % count0 can be used local
+ \count2\nofcolumns % count2 can be used local
+ \dohandleallcolumns
+ {\ifnum\count0>\zerocount % the wide one's reserved space
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\copy\currenttopcolumnbox
+ \hbox{\vphantom{\vskip\floatheight}}}% known from previous
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
\else
- \dimen0\dimexpr\count0\hsize+\count0\intercolumnwidth-\intercolumnwidth\relax
- \dofloatsflush\s!text{1}%
- \ifdim\floatwidth>\finalcolumntextwidth % better somewhere else too
- \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}%
- \fi % otherwise the graphic may disappear
- \global\setbox\floatbox\hbox to \dimen0
- {\processaction[\rootfloatparameter\c!location] % how easy to forget
- [ \v!left=>\box\floatbox\hss,
- \v!right=>\hss\box\floatbox,
- \s!default=>\hss\box\floatbox\hss,
- \s!unknown=>\hss\box\floatbox\hss]}%
+ \page_floats_get_info\s!text
+ \ifdim\floatwidth>\hsize
+ \dimen0\dimexpr\floatwidth+\d_page_mul_distance+.5pt\relax
+ \dimen2\dimexpr\hsize +\d_page_mul_distance+.5pt\relax
+ \divide\dimen0 \dimen2
+ \count0\dimen0
+ \advance\count0 \plusone
+ \ifnum\count0>\count2
+ \count0\zerocount
+ \else
+ \dimen0\dimexpr\count0\hsize+\count0\d_page_mul_distance-\d_page_mul_distance\relax
+ \page_floats_flush\s!text\plusone
+ \ifdim\floatwidth>\makeupwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ \global\setbox\floatbox\hbox to \dimen0
+ {\processaction[\rootfloatparameter\c!location] % how easy to forget
+ [ \v!left=>\box\floatbox\hss,
+ \v!right=>\hss\box\floatbox,
+ \s!default=>\hss\box\floatbox\hss,
+ \s!unknown=>\hss\box\floatbox\hss]}%
+ \fi
+ \showmessage\m!columns{13}\empty
+ \else
+ \page_floats_flush\s!text\plusone
+ \ifdim\floatwidth>\makeupwidth % better somewhere else too
+ \global\setbox\floatbox\hbox to \makeupwidth{\hss\box\floatbox\hss}%
+ \fi % otherwise the graphic may disappear
+ % \showmessage\m!columns{13}\empty
+ \fi
+ \ifdim\ht\floatbox>\zeropoint\relax
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox
+ {\box\currenttopcolumnbox % was copy
+ \box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \fi
+ \dimen6\htdp\currenttopcolumnbox
\fi
- \showmessage\m!columns{13}\empty
- \else
- \dofloatsflush\s!text{1}%
- \ifdim\floatwidth>\finalcolumntextwidth % better somewhere else too
- \global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}%
- \fi % otherwise the graphic may disappear
- % \showmessage\m!columns{13}\empty
- \fi
- \ifdim\ht\floatbox>\zeropoint\relax
- \global\setbox\currenttopcolumnbox\vbox
- {\snaptogrid\vbox
- {\box\currenttopcolumnbox % was copy
- \box\floatbox}
- \whitespace % nodig ?
- \blank[\rootfloatparameter\c!spaceafter]}%
- \fi
- \dimen6\htdp\currenttopcolumnbox
- \fi
- \ifdim\dimen4<\ht\currenttopcolumnbox
- \dimen4\ht\currenttopcolumnbox
- \fi
- \advance\dimen8 \dimen6
- \advance\count2 \minusone
- \advance\count0 \minusone }%
- \page_otr_command_set_vsize
- \global\advance\vsize -\dimen8
- \global\pagegoal\vsize
- \else
- % \page_mul_command_flush_floats % does not snap!
- \fi
- \egroup
- \fi}
+ \ifdim\dimen4<\ht\currenttopcolumnbox
+ \dimen4\ht\currenttopcolumnbox
+ \fi
+ \advance\dimen8 \dimen6
+ \advance\count2 \minusone
+ \advance\count0 \minusone }%
+ \page_otr_command_set_vsize
+ \global\advance\vsize -\dimen8
+ \pagegoal\vsize
+ \else
+ % \page_mul_command_flush_floats % does not snap!
+ \fi
+ \egroup
+ \fi}
%D The next macro can be used to flush floats in the current stream. No
%D width checking is (yet) done.
-\def\insertcolumnfloats
- {\doloop
- {\ifsomefloatwaiting
- \bgroup
- \forgetall
- % no check for width
- \dogetfloat
- \blank[\rootfloatparameter\c!spacebefore]
- \snaptogrid\vbox{\copy\floatbox}
- \blank[\rootfloatparameter\c!spaceafter]
- \egroup
- \else
- \exitloop
- \fi}}
+ \def\insertcolumnfloats
+ {\doloop
+ {\ifconditional\c_page_floats_some_waiting
+ \bgroup
+ \forgetall
+ % no check for width
+ \page_floats_get
+ \blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\copy\floatbox}
+ \blank[\rootfloatparameter\c!spaceafter]
+ \egroup
+ \else
+ \exitloop
+ \fi}}
%D This were the multi||column routines. They can and need to be improved
%D but at the moment their behaviour is acceptable.
@@ -1417,57 +1426,21 @@
% 3 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{3}}
% \stopcolumns
-\unexpanded\def\setupcolumns
- {\dosingleempty\dosetupcolumns}
-
-\def\dosetupcolumns[#1]%
- {\getparameters[\??kl][#1]%
- \nofcolumns\@@kln\relax
- \processaction
- [\@@klrule]
- [ \v!on=>\let\betweencolumns\linebetweencolumns,
- \v!off=>\let\betweencolumns\spacebetweencolumns,
- \s!default=>\let\betweencolumns\spacebetweencolumns,
- \s!unknown=>\let\betweencolumns\@@klrule]}
-
-\def\linebetweencolumns
- {\bgroup
- \starttextproperties
- \ifdim\@@kldistance>\zeropoint
- \dimen0=\@@kldistance
- \else
- \dimen0=\linewidth
- \fi
- \advance\dimen0 -\linewidth
- \hskip.5\dimen0
- \vrule
- \!!width\linewidth
- \ifnum\bottomraggednessmode=\plustwo % baselinebottom
- \!!depth\strutdepth
- \fi
- \hskip.5\dimen0\relax
- \stoptextproperties
- \egroup}
-
-\def\spacebetweencolumns
- {\hskip\@@kldistance}
-
-\presetlocalframed[\??kl]
-
-\def\backgroundfinishcolumnbox
- {\doifinsetelse\@@kloffset{\v!none,\v!overlay}
- {\let\@@kloffset\!!zeropoint}
- {\scratchdimen\@@kloffset
- \advance\scratchdimen -\@@klrulethickness
- \edef\@@kloffset{\the\scratchdimen}}%
- \localframed
- [\??kl]
- [\c!strut=\v!no,
- \c!width=\v!fit,
- \c!height=\v!fit,
- \c!align=]}
-
-\definecomplexorsimpleempty\startcolumns
+ % \def\backgroundfinishcolumnbox
+ % {\doifinsetelse\@@kloffset{\v!none,\v!overlay}
+ % {\let\@@kloffset\!!zeropoint}
+ % {\scratchdimen\@@kloffset
+ % \advance\scratchdimen -\@@klrulethickness
+ % \edef\@@kloffset{\the\scratchdimen}}%
+ % \localframed
+ % [\??kl]
+ % [\c!strut=\v!no,
+ % \c!width=\v!fit,
+ % \c!height=\v!fit,
+ % \c!align=]}
+
+ \def\backgroundfinishcolumnbox
+ {}
% to be reconsidered ... (in any case they need to be unexpandable sinze 2011.12.30)
@@ -1475,133 +1448,196 @@
\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
+\newtoks\t_page_mul_initialize
+
+\unexpanded\def\startcolumns
+ {\dosingleempty\page_mul_start}
+
+\def\page_mul_start[#1]% %% \startcolumns
{\bgroup
- \let\stopcolumns\egroup
\ifinsidecolumns
+ \page_mul_start_nop
\else
- \setupcolumns[#1]%
- \ifnum\@@kln>1\relax
- \whitespace
- \begingroup
- \doif\@@kloption\v!background
- {\let\finishcolumnbox\backgroundfinishcolumnbox
- \let\columntextoffset\@@kloffset}%
- \ifx\@@klcommand\empty\else
- \let\postprocesscolumnline\@@klcommand
- \fi
- \doifelsenothing\@@klheight
- \heightencolumnsfalse
- \heightencolumnstrue
- \doifelse\@@kldirection\v!right
- \reversecolumnsfalse
- \reversecolumnstrue
- \doifelse\@@klbalance\v!yes
- \balancecolumnstrue
- \balancecolumnsfalse
- \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
- \edef\fixedcolumnheight{\@@klheight}%
- \edef\minbalancetoplines{\@@klntop}%
- \setuptolerance[\@@kltolerance]% %% \startcolumns
- \setupblank[\@@klblank]%
- \ifdim\s_spac_whitespace_parskip>\zeropoint\relax
- \setupwhitespace[\@@klblank]%
- \fi
- \unexpanded\def\stopcolumns
- {\endmulticolumns
- \global\insidecolumnsfalse
- \endgroup
- \egroup}%
- \global\insidecolumnstrue
- \beginmulticolumns
+ \iffirstargument
+ \setupcolumns[#1]%
+ \fi
+ \nofcolumns\columnsparameter\c!n\relax
+ \ifnum\nofcolumns>\plusone
+ \page_mul_start_yes
+ \else
+ \page_mul_start_nop
\fi
\fi}
-\installcolumnbreakmethod \s!multicolumn \v!preference
- {\goodbreak}
+\unexpanded\def\page_mul_start_nop
+ {\let\stopcolumns\page_mul_stop_nop}
-\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 interwoven and therefore
-%D to be integrated when the multi column modules are merged.
-
-\unexpanded\def\setupcolumnspan[#1]%
- {\getparameters[\??ks][#1]}
-
-\presetlocalframed
- [\??ks]
+\unexpanded\def\page_mul_stop_nop
+ {\egroup}
-\setupcolumnspan
- [\c!n=2,
- \c!offset=\v!overlay,
- \c!frame=\v!off]
+\unexpanded\def\page_mul_start_yes
+ {\whitespace
+ \begingroup
+ \let\stopcolumns\page_mul_stop_indeed
+ \global\insidecolumnstrue
+ \the\t_page_mul_initialize
+ %
+ \flushnotes
+ \begingroup
+ %
+ \d_page_mul_leftskip\leftskip
+ \d_page_mul_rightskip\rightskip
+ \leftskip\zeropoint
+ \rightskip\zeropoint
+ %
+ \widowpenalty\zerocount % will become option
+ \clubpenalty \zerocount % will become option
+ %
+ \page_floats_column_push_saved
+ %
+ \ifdim\dimexpr\pagetotal+\parskip+\openlineheight\relax<\pagegoal
+ \allowbreak
+ \else
+ \break % sometimes fails
+ \fi
+ \appendtoks
+ \topskip1\topskip % best a switch
+ \to \everybodyfont
+ \the\everybodyfont % ugly here
+ \saveinterlinespace % ugly here
+ %
+ \initializecolumns\nofcolumns
+ %
+ \hangafter\zerocount
+ \hangindent\zeropoint
+ \reseteverypar
+ \ifdim\pagetotal=\zeropoint \else
+ \verticalstrut
+ \vskip-\struttotal
+ \fi
+ \global\savedpagetotal\pagetotal
+ \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\d_page_mul_preceding_height\ht\b_page_mul_preceding
+ \c_page_mul_routine\c_page_mul_routine_continue
+ \page_mul_initialize_floats
+ \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}%
+ \checkbegincolumnfootnotes
+ \page_otr_command_set_hsize
+ \page_otr_command_set_vsize}
-\newbox\b_page_columns_span \let\postprocesscolumnspanbox\gobbleoneargument
+\setnewconstant\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
-\def\dostartcolumnspan[#1]%
- {\bgroup
- \setupcolumnspan[#1]%
- \forgetall
- \ifinsidecolumns
- \advance\hsize \intercolumnwidth
- \hsize\@@ksn\hsize
- \advance\hsize -\intercolumnwidth
+\unexpanded\def\page_mul_stop_indeed
+ {\relax
+ \ifnum\multicolumnendsyncmethod=\plustwo
+ \synchronizeoutput
+ \else
+ % don't collapse these
+ \vskip \lineheight
+ \vskip-\lineheight % take footnotes into account
\fi
- \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}
+ \doflushcolumnfloat % added recently
+ %\doflushcolumnfloats % no, since it results in wrong top floats
+ \flushnotes % before start of columns
+ \par
+ \ifbalancecolumns
+ \ifnum\multicolumnendsyncmethod=\plusone
+ \c_page_mul_routine\c_page_mul_routine_continue
+ \goodbreak
\fi
+ \c_page_mul_routine\c_page_mul_routine_balance
\else
- \snaptogrid\vbox{\box\b_page_columns_span}
+ \goodbreak
\fi
- \endgraf
- \ifvmode\prevdepth\strutdp\fi
- \egroup}
+ % 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
+ %
+ \c_page_mul_routine\c_page_mul_routine_regular
+ %
+ \ifvoid\b_page_mul_preceding\else
+ \unvbox\b_page_mul_preceding
+ \fi
+ \global\d_page_mul_preceding_height\zeropoint
+ \endgroup % here
+ \nofcolumns\plusone
+ \page_otr_command_set_vsize
+ \checkendcolumnfootnotes
+ \dosomebreak\allowbreak
+ \page_floats_column_pop_saved
+ %
+ \global\insidecolumnsfalse
+ \endgroup
+ \egroup}%
+
+\appendtoks
+ \edef\p_option{\columnsparameter\c!option}%
+ \ifx\p_option\v!background
+ \let\finishcolumnbox\backgroundfinishcolumnbox
+ \fi
+ \d_page_mul_offset\columnsparameter\c!offset\relax
+ \edef\p_command{\columnsparameter\c!command}%
+ \ifx\p_command\empty \else
+ \let\postprocesscolumnline\p_command
+ \fi
+ \edef\p_height{\columnsparameter\c!height}%
+ \ifx\p_height\empty
+ \d_page_mul_forced_height\textheight
+ \heightencolumnsfalse
+ \else
+ \d_page_mul_forced_height\p_height\relax
+ \heightencolumnstrue
+ \fi
+ \edef\p_direction{\columnsparameter\c!direction}%
+ \ifx\p_direction\v!right
+ \setfalse\c_page_mul_reverse
+ \else
+ \settrue\c_page_mul_reverse
+ \fi
+ \edef\p_balance{\columnsparameter\c!balance}%
+ \ifx\p_balance\v!yes
+ \balancecolumnstrue
+ \else
+ \balancecolumnsfalse
+ \fi
+ \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
+ \edef\p_align{\columnsparameter\c!align}%
+ \ifx\p_align\empty \else
+ \setupalign[\p_align]%
+ \fi
+ \edef\p_tolerance{\columnsparameter\c!tolerance}%
+ \ifx\p_tolerance\empty \else
+ \setuptolerance[\p_tolerance]%
+ \fi
+ \edef\p_blank{\columnsparameter\c!blank}%
+ \ifx\p_blank\empty \else
+ \setupblank[\p_blank]%
+ \fi
+ \ifdim\s_spac_whitespace_parskip>\zeropoint\relax
+ \setupwhitespace[\p_blank]%
+ \fi
+ \c_page_mul_balance_minimum\columnsparameter\c!ntop\relax
+ \edef\p_page_mul_rule{\columnsparameter\c!rule}%
+ \expandcheckedcsname\??columnseparators\p_page_mul_rule\s!unknown
+\to \t_page_mul_initialize
+
+%D Columns breaks
-\unexpanded\def\startcolumnspan
- {\dosingleempty\dostartcolumnspan}
+\installcolumnbreakmethod \s!multicolumn \v!preference
+ {\goodbreak}
-\unexpanded\def\stopcolumnspan
- {\egroup}
+\installcolumnbreakmethod \s!multicolumn \v!yes
+ {\vskip\textheight
+ \penalty-200 % we can mark and intercept this
+ \vskip-\textheight}
+
+%D Next we initialize the lot:
\setupcolumns
[\c!n=2,
@@ -1619,19 +1655,85 @@
\c!rulethickness=\linewidth,
\c!offset=.5\bodyfontsize]
-%D Undocumented and still under development.
+%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]}
+
+ \presetlocalframed
+ [\??ks]
+
+ \setupcolumnspan
+ [\c!n=2,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+ \newbox\b_page_columns_span \let\page_mul_postprocess_spanbox\gobbleoneargument
+
+ \unexpanded\def\startcolumnspan
+ {\dosingleempty\dostartcolumnspan}
+
+ \unexpanded\def\stopcolumnspan
+ {\egroup}
+
+ \def\dostartcolumnspan[#1]%
+ {\bgroup
+ \setupcolumnspan[#1]%
+ \forgetall
+ \ifinsidecolumns
+ \advance\hsize \d_page_mul_distance
+ \hsize\@@ksn\hsize
+ \advance\hsize -\d_page_mul_distance
+ \fi
+ \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
+ \page_mul_postprocess_spanbox\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}
+ \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}
+
+%D Undocumented and still under development.\ifdefined\startsimplecolumns \else
\unexpanded\def\startsimplecolumns
- {\dosingleempty\dostartsimplecolumns}
+ {\dosingleempty\page_mul_simple_start}
-\def\dostartsimplecolumns[#1]%
+\def\page_mul_simple_start[#1]%
{\bgroup
+ \setsimplecolumnshsize[#1]%
\nopenalties
- \getparameters[\??kl]
- [\c!width=\hsize,\c!distance=1.5\bodyfontsize,%
- \c!n=2,\c!lines=0,#1]%
- \let\rigidcolumnlines\@@kllines
- \setrigidcolumnhsize\@@klwidth\@@kldistance\@@kln
\setbox\scratchbox\vbox\bgroup
\forgetall} % \blank[\v!disable]
@@ -1642,35 +1744,44 @@
\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}
+ {\getdummyparameters
+ [\c!width=\hsize,
+ \c!distance=1.5\bodyfontsize,
+ \c!n=2,
+ \c!lines=0,
+ #1]%
+ \edef\rigidcolumnlines
+ {\directdummyparameter\c!lines}%
+ \setrigidcolumnhsize
+ {\directdummyparameter\c!width}%
+ {\directdummyparameter\c!distance}%
+ {\directdummyparameter\c!n}}
\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
+ [\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/tex/context/base/page-not.mkiv b/tex/context/base/page-not.mkiv
index 06e2f3875..d7602bd26 100644
--- a/tex/context/base/page-not.mkiv
+++ b/tex/context/base/page-not.mkiv
@@ -13,12 +13,12 @@
\writestatus{loading}{ConTeXt Page Macros / Footnotes}
-%D Terrible hacks: we need to share save/restore
+%D This is an old mechanism that will be replaced as soon as the multicolumn
+%D code is redone.
-%D We've moved some footnote handling to a separate page
-%D module. The macros below are used in the single and multi
-%D column page handlers and permit mixed usage of column and
-%D page notes.
+%D We've moved some footnote handling to a separate page module. The macros below
+%D are used in the single and multi column page handlers and permit mixed usage of
+%D column and page notes.
\unprotect
@@ -41,11 +41,13 @@
\newdimen\totalinsertionheight
-\def\settotalinsertionheight
+\unexpanded\def\settotalinsertionheight
{\calculatetotalnoteheight
- \totalinsertionheight\totalnoteheight
- \addinsertionheight\topins\to\totalinsertionheight
- \addinsertionheight\botins\to\totalinsertionheight}
+ \totalinsertionheight\dimexpr
+ \totalnoteheight
+ +\page_insert_insertion_height\s!topfloat
+ +\page_insert_insertion_height\s!bottomfloat
+ \relax}
% hm
diff --git a/tex/context/base/page-one.mkiv b/tex/context/base/page-one.mkiv
index 89fd7d4a8..6261938b6 100644
--- a/tex/context/base/page-one.mkiv
+++ b/tex/context/base/page-one.mkiv
@@ -20,7 +20,7 @@
% OTRONE: basic single column
-\newdimen\d_page_one_saved_vsize
+\newconstant \c_page_one_float_method
\unexpanded\def\page_one_command_next_page
{\page_otr_eject_page}
@@ -34,6 +34,34 @@
\unexpanded\def\page_one_command_set_float_hsize
{\global\hsize\textwidth}
+% \newdimen\d_page_one_saved_vsize
+%
+% \unexpanded\def\page_one_command_set_vsize
+% {\ifgridsnapping
+% \ifcase\layoutlines
+% \getrawnoflines\textheight
+% \else
+% \noflines\layoutlines
+% \fi
+% \global\vsize\noflines\openlineheight
+% \else
+% \global\vsize\textheight
+% \fi
+% \ifdim\pagegoal<\maxdimen
+% \ifdim\d_page_one_saved_vsize=\vsize
+% % let's assume that the layout didn't change
+% \else
+% \global\d_page_one_saved_vsize\vsize
+% \pagegoal\dimexpr\vsize-\d_page_floats_inserted_top-\d_page_floats_inserted_bottom\relax
+% % \bgroup
+% % \global\d_page_one_saved_vsize\vsize
+% % \advance\vsize-\d_page_floats_inserted_top
+% % \advance\vsize-\d_page_floats_inserted_bottom
+% % \pagegoal\vsize
+% % \egroup
+% \fi
+% \fi}
+
\unexpanded\def\page_one_command_set_vsize
{\ifgridsnapping
\ifcase\layoutlines
@@ -45,20 +73,10 @@
\else
\global\vsize\textheight
\fi
- \ifdim\pagegoal<\maxdimen
- \ifdim\d_page_one_saved_vsize=\vsize
- % let's assume that the layout didn't change
- \else
- \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}
+ % alternatively we could set it in builders.buildpage_filter
+ % \ifdim\pagegoal<\maxdimen .. \fi
+ \global\pagegoal\dimexpr\vsize-\d_page_floats_inserted_top-\d_page_floats_inserted_bottom\relax}
+
% 1 = partial page, 2 = whole page, 3 = partial page
@@ -186,31 +204,32 @@
\newskip \s_page_one_between_top_insert
\def\page_one_prepare_top_float
- {\ifdim\topinserted=\zeropoint
+ {\ifdim\d_page_floats_inserted_top=\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}
+ \s_page_one_between_top_insert\ifdim\d_strc_floats_top>\d_strc_floats_bottom\d_strc_floats_top\else\d_strc_floats_bottom\fi\relax
+ \global\advance\d_page_floats_inserted_top\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}}
+ {\insert\namedinsertionnumber\s!topfloat\bgroup
+ \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
+ \egroup}
\unexpanded\def\page_one_command_set_top_insertions
{\bgroup
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\noffloatinserts\zerocount
\let\totaltopinserted\!!zeropoint
\page_one_command_set_top_insertions_indeed
@@ -228,25 +247,25 @@
\egroup}
\def\page_one_command_set_top_insertions_indeed
- {\ifnum\noffloatinserts<\noftopfloats
- \dogetfloat
+ {\ifnum\noffloatinserts<\c_page_floats_n_of_top
+ \page_floats_get
\page_one_prepare_top_float
- \ifdim\topinserted<\textheight\relax
- \xdef\totaltopinserted{\the\topinserted}%
+ \ifdim\d_page_floats_inserted_top<\textheight\relax
+ \xdef\totaltopinserted{\the\d_page_floats_inserted_top}%
\page_one_insert_top_float
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\advance\noffloatinserts \plusone
\else
- \noffloatinserts\noftopfloats\relax
+ \noffloatinserts\c_page_floats_n_of_top\relax
\fi
- \dofloatflushedinfo
+ \page_floats_report_flushed
\else
- \doresavefloat
- \noffloatinserts\noftopfloats\relax
+ \page_floats_resave\s!text
+ \noffloatinserts\c_page_floats_n_of_top\relax
\fi
\else
- \ifsomefloatwaiting
- \showmessage\m!floatblocks6{\the\noftopfloats}%
+ \ifconditional\c_page_floats_some_waiting
+ \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}%
\fi
\let\page_one_command_set_top_insertions_indeed\relax
\fi
@@ -254,101 +273,98 @@
\unexpanded\def\page_one_command_set_bottom_insertions
{\bgroup
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\noffloatinserts\zerocount
\page_one_command_set_bottom_insertions_indeed
\fi
\egroup}
\def\page_one_command_set_bottom_insertions_indeed
- {\ifnum\noffloatinserts<\nofbotfloats\relax
- \dogetfloat
- \global\advance\botinserted \ht\floatbox\relax
- \global\advance\botinserted \dp\floatbox\relax
- \global\advance\botinserted \floattopskip\relax
- \ifdim\botinserted<\pagegoal\relax
- \insert\botins
- {\forgetall
- \blank[\rootfloatparameter\c!spacebefore]%
- \page_otr_command_flush_float_box}%
- \ifsomefloatwaiting
+ {\ifnum\noffloatinserts<\c_page_floats_n_of_bottom\relax
+ \page_floats_get
+ \global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
+ \ifdim\d_page_floats_inserted_bottom<\pagegoal\relax
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
+ \ifconditional\c_page_floats_some_waiting
\advance\noffloatinserts \plusone
\else
- \noffloatinserts\nofbotfloats
+ \noffloatinserts\c_page_floats_n_of_bottom
\fi
- \dofloatflushedinfo
+ \page_floats_report_flushed
\else
- \doresavefloat
- \noffloatinserts\nofbotfloats\relax
+ \page_floats_resave\s!text
+ \noffloatinserts\c_page_floats_n_of_bottom\relax
\fi
- \global\nofloatpermittedtrue % vgl topfloats s!
+ \global\settrue\c_page_floats_not_permitted % vgl topfloats s!
\else
- \ifsomefloatwaiting
- \showmessage\m!floatblocks7{\the\nofbotfloats}%
+ \ifconditional\c_page_floats_some_waiting
+ \showmessage\m!floatblocks7{\the\c_page_floats_n_of_bottom}%
\fi
\let\page_one_command_set_bottom_insertions_indeed\relax
\fi
\page_one_command_set_bottom_insertions_indeed}
-\newconstant\topinserttopskipmode % 1 = no topskip
-
\unexpanded\def\page_one_command_flush_top_insertions
- {\ifvoid\topins\else
+ {\ifvoid\namedinsertionnumber\s!topfloat\else
\ifgridsnapping
- \box\topins
+ \box\namedinsertionnumber\s!topfloat
\vskip-\topskip
\vskip\strutheight % [xx] new: see icare topbleed
\else
- \ifcase\topinserttopskipmode
+ \ifcase\c_page_floats_insertions_topskip_mode
% 0: default, do nothing
\or
% 1: no topskip (crossed fingers)
\vskip-\topskip
\vskip\strutheight
\fi
- \unvbox\topins
+ \unvbox\namedinsertionnumber\s!topfloat
\fi
\fi
- \global\topinserted\zeropoint}
+ \global\d_page_floats_inserted_top\zeropoint}
\unexpanded\def\page_one_command_flush_bottom_insertions
- {\ifvoid\botins\else
+ {\ifvoid\namedinsertionnumber\s!bottomfloat\else
\ifgridsnapping
% \floatparameter\c!bottombefore
- \snaptogrid\hbox{\box\botins}%
+ \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}%
% \floatparameter\c!bottomafter
\else
\floatparameter\c!bottombefore
- \unvbox\botins
+ \unvbox\namedinsertionnumber\s!bottomfloat
\floatparameter\c!bottomafter
\fi
\fi
- \global\botinserted\zeropoint
- \global\nofloatpermittedfalse}
+ \global\d_page_floats_inserted_bottom\zeropoint
+ \global\setfalse\c_page_floats_not_permitted}
\unexpanded\def\page_one_command_flush_floats
- {\global\flushingfloatstrue
- \ifsomefloatwaiting
+ {\global\settrue\c_page_floats_flushing
+ \ifconditional\c_page_floats_some_waiting
\par
% if kept, then option and definitely off in gridmode ! ! ! !
% \ifvmode \prevdepth\maxdimen \fi % prevents whitespace; problematic in icare tests
\page_one_command_flush_floats_indeed
\fi
\global\savednoffloats\zerocount
- \global\somefloatwaitingfalse
- \global\flushingfloatsfalse}
+ \global\setfalse\c_page_floats_some_waiting
+ \global\setfalse\c_page_floats_flushing}
\unexpanded\def\page_one_command_flush_float_box
- {\ifcenterfloatbox \ifdim\wd\floatbox<\hsize
+ {\ifconditional\c_page_floats_center_box \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
+ \snaptogrid\hbox{\box\floatbox}} % was copy
\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}%
+ {\ifconditional\c_page_floats_some_waiting
+ \ifconditional\c_page_floats_pack_flushed
+ \setfalse\c_page_floats_center_box % not needed as we do call directly
+ \page_floats_collect\s!text\hsize\emwidth
%% no longer (interferes with footnotes):
%%
%% \page_one_command_set_vsize % test 2011.06.24.001
@@ -357,9 +373,9 @@
{\hfil
\dorecurse\nofcollectedfloats
{\ifcase\columndirection % nog document wide
- \dofloatsflush\s!text{1}%
+ \page_floats_flush\s!text\plusone
\else
- \dofloatsflush\s!text{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}%
+ \page_floats_flush\s!text{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}%
\fi
\ifdim\wd\floatbox>\makeupwidth % \hsize
\hbox to \makeupwidth{\hss\box\floatbox\hss}%
@@ -371,7 +387,7 @@
\fi}%
\hfil}%
\else
- \dogetfloat
+ \page_floats_get
\fi
% there is a chance that due to rounding errors, the float
% fits on a page where it was first rejected, in which case
@@ -394,8 +410,8 @@
\fi}
\unexpanded\def\page_one_command_check_if_float_fits
- {\ifnofloatpermitted
- \global\roomforfloatfalse
+ {\ifconditional\c_page_floats_not_permitted
+ \global\setfalse\c_page_floats_room
\else
% new per 31/5/2004, should be an option, only one column mode
\begingroup
@@ -405,10 +421,10 @@
\fi
% should be an option
\endgroup
- \dimen0\dimexpr\pagetotal+\floatheight+\floattopskip-\pageshrink\relax
+ \dimen0\dimexpr\pagetotal+\floatheight+\d_strc_floats_top-\pageshrink\relax
\dimen2\pagegoal
\relax % needed
- \ifcase\textfloatmethod
+ \ifcase\c_page_one_float_method
% method 0 : raw
\or
% method 1 : safe
@@ -419,19 +435,19 @@
\fi
\relax % really needed ! ! ! !
\ifdim\dimen0>\dimen2
- \global\roomforfloatfalse
+ \global\setfalse\c_page_floats_room
\else
- \global\roomforfloattrue
+ \global\settrue\c_page_floats_room
\fi
\fi}
\unexpanded\def\page_one_command_flush_saved_floats
- {\global\topinserted\zeropoint
- \global\botinserted\zeropoint
- \ifflushingfloats \else
+ {\global\d_page_floats_inserted_top\zeropoint
+ \global\d_page_floats_inserted_bottom\zeropoint
+ \ifconditional\c_page_floats_flushing \else
\page_one_command_set_top_insertions
\page_one_command_set_bottom_insertions
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\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
@@ -443,7 +459,7 @@
\baselinecorrection
%\fi
\doplacefloatbox
- \doinsertfloatinfo
+ \page_floats_report_total
\dohandlenextfloatindent}
\def\page_one_place_float_force
@@ -469,10 +485,10 @@
%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_page {\page_floats_save_page_float \s!page \floatlocationmethod}
+\def\page_one_place_float_leftpage {\page_floats_save_page_float \s!leftpage \floatlocationmethod}
+\def\page_one_place_float_rightpage {\page_floats_save_page_float \s!rightpage\floatlocationmethod}
+\def\page_one_place_float_somewhere {\page_floats_save_somewhere_float\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}
@@ -488,38 +504,41 @@
{\doifinsetelse\v!always\floatlocationmethod
{\page[\v!preference]%
\page_otr_command_check_if_float_fits
- \ifroomforfloat
+ \ifconditional\c_page_floats_room
\page_one_place_float_here_indeed
\else
\showmessage\m!floatblocks9\empty
- \doreversesavefloat
+ \page_floats_resave\s!text
\fi}
- {\ifsomefloatwaiting
- \dosavefloat
+ {\ifconditional\c_page_floats_some_waiting
+ \page_floats_save\s!text
+ \nonoindentation
\else
\page[\v!preference]%
\page_otr_command_check_if_float_fits
- \ifroomforfloat
+ \ifconditional\c_page_floats_room
\page_one_place_float_here_indeed
\else
- \dosavefloat
+ \page_floats_save\s!text
+ \nonoindentation
\fi
\fi}}
\def\page_one_place_float_otherwise_else
{\doifinsetelse\v!always\floatlocationmethod
{\page_otr_command_check_if_float_fits
- \ifroomforfloat
+ \ifconditional\c_page_floats_room
\page_one_place_float_auto_top_bottom
\else
\showmessage\m!floatblocks9\empty
- \doreversesavefloat
+ \page_floats_resave\s!text
\fi}
{\page_otr_command_check_if_float_fits
- \ifroomforfloat
+ \ifconditional\c_page_floats_room
\page_one_place_float_auto_top_bottom
\else
- \dosavefloat
+ \page_floats_save\s!text
+ \nonoindentation
\fi}}
\def\floatautofactor{.5}
@@ -544,23 +563,23 @@
\def\page_one_place_float_top_indeed % maybe remember last beforeskip
{\page_one_prepare_top_float
\page_one_insert_top_float
- \doinsertfloatinfo}
+ \page_floats_report_total}
\def\page_one_place_float_bottom_indeed
- {\global\advance\botinserted\dimexpr\ht\floatbox+\dp\floatbox+\floattopskip\relax
- \insert\botins
- {\forgetall
- \blank[\rootfloatparameter\c!spacebefore]%
- \page_otr_command_flush_float_box}%
- %\global\nofloatpermittedtrue
- \doinsertfloatinfo}
+ {\global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
+ \page_floats_report_total}
\def\page_one_place_float_face % links, rechts, midden, hoog, midden, laag
{%\checkwaitingfloats{#1}%
\startopposite
\page_otr_command_flush_float_box
\stopopposite
- }%\doinsertfloatinfo}
+ }%\page_floats_report_total}
\unexpanded\def\page_one_command_flush_side_floats
{\page_sides_flush_floats}
diff --git a/tex/context/base/page-otr.mkvi b/tex/context/base/page-otr.mkvi
index 19c308c32..e5433c866 100644
--- a/tex/context/base/page-otr.mkvi
+++ b/tex/context/base/page-otr.mkvi
@@ -258,8 +258,8 @@
\definesystemconstant{page_otr_command_flush_margin_blocks}
\definesystemconstant{singlecolumn}
-\definesystemconstant{multicolumn}
-\definesystemconstant{columnset}
+\definesystemconstant{multicolumn} % will move
+\definesystemconstant{columnset} % will move
\defineoutputroutinecommand
[\s!page_otr_command_routine,
diff --git a/tex/context/base/page-par.mkiv b/tex/context/base/page-par.mkiv
index 26e306ef5..588065d65 100644
--- a/tex/context/base/page-par.mkiv
+++ b/tex/context/base/page-par.mkiv
@@ -15,49 +15,59 @@
\unprotect
-\newcount\internalparagraphnumber
-
-\unexpanded\def\setupparagraphnumbering
- {\dosingleempty\dosetupparagraphnumbering}
-
-\def\dosetupparagraphnumbering[#1]%
- {\getparameters
- [\??ph][#1]%
- \processaction
- [\@@phstate]
- [\v!start=>\let\showparagraphnumber\doshowparagraphnumberA,
- \v!stop=>\let\showparagraphnumber\relax,
- \v!line=>\let\showparagraphnumber\doshowparagraphnumberB,
- \v!reset=>\global\internalparagraphnumber\zerocount
- \let\showparagraphnumber\doshowparagraphnumberA]}
-
-\def\dodoshowparagraphnumber
- {\global\advance\internalparagraphnumber \plusone
- \inleftmargin % \tf normalizes em
- {\tf
- \dousestyleparameter\@phstyle
- \dousecolorparameter\@phcolor
- \the\internalparagraphnumber
- \kern\@@phdistance}}
-
-\def\doshowparagraphnumberA
- {%\ifprocessingverbatim
- % \iflinepar
- % % obsolete: \dodoshowparagraphnumber
- % \fi
- %\else
- \dodoshowparagraphnumber
- }%\fi}
-
-\def\doshowparagraphnumberB
+\installcorenamespace {paragraphnumbering}
+\installcorenamespace {paragraphnumberingvariants}
+
+\installsimplecommandhandler \??paragraphnumbering {paragraphnumbering} \??paragraphnumbering
+
+\definecounter[\v!paragraph]
+
+\let\showparagraphnumber\relax
+
+\appendtoks
+ \page_par_check_state
+\to \everysetupparagraphnumbering
+
+\unexpanded\def\page_par_check_state
+ {\rawprocesscommacommand[\paragraphnumberingparameter\c!state]\page_par_check_state_step}
+
+\def\page_par_check_state_step#1%
+ {\ifcsname\??paragraphnumberingvariants#1\endcsname
+ \csname\??paragraphnumberingvariants#1\endcsname
+ \fi}
+
+\setvalue{\??paragraphnumberingvariants\v!start}%
+ {\let\showparagraphnumber\page_par_show_number_normal}
+
+\setvalue{\??paragraphnumberingvariants\v!stop}%
+ {\let\showparagraphnumber\relax}
+
+\setvalue{\??paragraphnumberingvariants\v!line}%
+ {\let\showparagraphnumber\page_par_show_number_lines}
+
+\setvalue{\??paragraphnumberingvariants\v!reset}%
+ {\strc_counters_reset\v!paragraph
+ \let\showparagraphnumber\page_par_show_number_normal}
+
+\unexpanded\def\page_par_show_number_normal
+ {\strc_counters_increment\v!paragraph
+ \inleftmargin % todo: \c!location, only a few make sense
+ {\hfill % no complaints
+ \tf % \tf normalizes em
+ \useparagraphnumberingstyleandcolor\c!style\c!color
+ \convertedcounter[\v!paragraph]%
+ \kern\paragraphnumberingparameter\c!distance}}
+
+\unexpanded\def\page_par_show_number_lines
{\ifnumberinglines
- \doshowparagraphnumberA
+ \page_par_show_number_normal
\fi}
\setupparagraphnumbering
[\c!state=\v!stop,
- \c!style=,
- \c!color=,
- \c!distance=\ifcase\linenumberlocation2em\else\!!zeropoint\fi] % will change
+ %\c!location,
+ %\c!style=,
+ %\c!color=,
+ \c!distance=\ifcase\c_page_lines_location2\emwidth\else\zeropoint\fi] % will change
\protect \endinput
diff --git a/tex/context/base/page-plg.mkiv b/tex/context/base/page-plg.mkiv
index 004b9204d..b59a05a94 100644
--- a/tex/context/base/page-plg.mkiv
+++ b/tex/context/base/page-plg.mkiv
@@ -11,10 +11,11 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% \ifx\pageareabox\undefined \else \endinput \fi
-
\writestatus{loading}{ConTeXt Page Macros / Extra Page Building}
+%D This still needs some work, especially the dimensions need to be
+%D checked cq.\ optimized. Beware: method has become alternative!
+
%D This feature has been present for a while but has never been
%D exploited: pluggable pagebuilders. The next example code
%D demonstrates the application of one such a plug-in. This variant
@@ -31,6 +32,8 @@
%D \startpagelayout[leftpage]
%D \setupTABLE[offset=overlay]
%D \setupTABLE[c][1][width=\leftmarginwidth]
+%D \setupTABLE[c][2][width=\textwidth]
+%D \setupTABLE[c][3][width=\rightmarginwidth]
%D \bTABLE
%D \bTR
%D \bTD[nx=3,background=color,backgroundcolor=green]
@@ -43,7 +46,7 @@
%D \eTR
%D \bTR
%D \bTD[nx=3,offset=overlay]
-%D {\bTABLE[width=.5\hsize]
+%D {\bTABLE
%D \bTR
%D \bTD \pagearea[footer][text][left] \eTD
%D \bTD \pagearea[bottom][text][left] \eTD
@@ -56,7 +59,9 @@
%D
%D \startpagelayout[rightpage]
%D \setupTABLE[offset=overlay]
-%D \setupTABLE[c][1][width=\rightmarginwidth]
+%D \setupTABLE[c][1][width=\leftmarginwidth]
+%D \setupTABLE[c][2][width=\textwidth]
+%D \setupTABLE[c][3][width=\rightmarginwidth]
%D \bTABLE
%D \bTR
%D \bTD[nx=3] \pagearea[header][text][middle] \eTD
@@ -67,7 +72,7 @@
%D \eTR
%D \bTR
%D \bTD[nx=3,offset=overlay]
-%D {\bTABLE[width=.5\hsize]
+%D {\bTABLE
%D \bTR
%D \bTD \pagearea[bottom][text][right] \eTD
%D \bTD \pagearea[footer][text][right] \eTD
@@ -80,12 +85,9 @@
%D
%D \setupcolors[state=start]
%D
-%D \setupbackgrounds[text][background=color,backgroundcolor=blue]
-%D \setupbackgrounds[header][text][background=color,backgroundcolor=red]
-%D
%D \setuppagenumbering[alternative=doublesided,location=]
%D
-%D \setuplayout[method=makeup]
+%D \setuplayout[alternative=makeup]
%D
%D \definetextbackground
%D [test]
@@ -110,6 +112,8 @@
\unprotect
+\installcorenamespace{layoutmakeupalternative}
+
\def\page_boxes_construct_content_makeup#1#2#3% targetbox flusher box
{\setbox#1\hbox
{\vbox to \textheight
@@ -125,65 +129,77 @@
\dp#1\zeropoint
\hsize\paperwidth
\vsize\paperheight
- \setbox#1\vbox{\csname\??layoutmethod\doifbothsidesoverruled\v!page\v!rightpage\v!leftpage\endcsname}%
+ \setbox#1\vbox{\csname\??layoutmakeupalternative\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
+\newbox\b_page_area
\unexpanded\def\pagearea
{\dotripleempty\page_area}
-\def\page_area[#1][#2][#3]%
+\def\page_area
{\ifthirdargument
- \doifelse{#3}\v!left
- {\page_area_indeed{#1}{#2}\c!lefttext}
- {\doifelse{#3}\v!right
- {\page_area_indeed{#1}{#2}\c!righttext}
- {\page_area_indeed{#1}{#2}\c!middletext}}%
+ \expandafter\page_area_three
\else\ifsecondargument
- \doifbothsidesoverruled
- {\page_area_indeed{#1}{#2}\c!righttext}
- {\page_area_indeed{#1}{#2}\c!righttext}
- {\page_area_indeed{#1}{#2}\c!lefttext }%
+ \doubleexpandafter\page_area_two
\else
- \doif{#1}\v!text % copy due to trial runs in TABLE
- {\iftrialtypesetting
-% \copy\pagebox
- \fakebox\pagebox
- \else
-% \localpositioningfalse
- \page_backgrounds_add_to_text\pagebox
- \page_grids_add_to_box\pagebox
- \box\pagebox
- \fi}%
+ \doubleexpandafter\page_area_one
\fi\fi}
-\def\page_area_indeed#1#2#3%
- {\setbox\pageareabox\vbox{\getspecificlayouttext{#1}{#2}{#3}}%
- \ifsomebackgroundfound{#1#2}%
+\def\page_area_three[#1][#2][#3]%
+ {\edef\m_page_area_three{#3}%
+ \ifx\m_page_area_three\v!left
+ \let\m_page_area_three\c!lefttext
+ \else\ifx\m_page_area_three\v!right
+ \let\m_page_area_three\c!righttext
+ \else
+ \let\m_page_area_three\c!middletext
+ \fi\fi
+ \page_area_indeed{#1}{#2}\m_page_area_three}
+
+\def\page_area_two[#1][#2][#3]%
+ {\edef\m_page_area_three{\doifbothsidesoverruled\c!righttext\c!righttext\c!lefttext}%
+ \page_area_indeed{#1}{#2}\m_page_area_three}
+
+\def\page_area_one[#1][#2][#3]%
+ {\edef\m_page_area_one{#1}
+ \ifx\m_page_area_one\v!text % copy due to trial runs in TABLE
\iftrialtypesetting
-% \box\pageareabox
- \fakebox\pageareabox
+ \fakebox\pagebox
\else
- \localframed
- [\??ma#1#2]
- [\c!width=\wd\pageareabox,
- \c!height=\ht\pageareabox,
- \c!offset=\v!overlay]
- {\box\pageareabox}%
+ \page_backgrounds_add_to_text\pagebox
+ \page_grids_add_to_box\pagebox
+ \box\pagebox
\fi
- \else
- \box\pageareabox
\fi}
+\def\page_area_indeed#1#2#3%
+ {\setbox\b_page_area\vbox{\getspecificlayouttext{#1}{#2}{#3}}%
+ \iftrialtypesetting
+ \fakebox\b_page_area
+ \else\ifcsname\??layoutbackgrounds#1#2\endcsname
+ \page_area_indeed_yes{#1}{#2}%
+ \else
+ \box\b_page_area
+ \fi\fi}
+
+\def\page_area_indeed_yes#1#2%
+ {% todo: \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}
+ \localframed % todo:
+ [\??layoutbackgrounds#1#2]
+ [\c!width=\wd\b_page_area,
+ \c!height=\ht\b_page_area,
+ \c!offset=\v!overlay]
+ {\box\b_page_area}}
+
% to be done nicely (proper namespacing)
-\setvalue{\??layoutmethod\v!leftpage }{\csname\??layoutmethod\v!page\endcsname}
-\setvalue{\??layoutmethod\v!rightpage}{\csname\??layoutmethod\v!page\endcsname}
+\setvalue{\??layoutmakeupalternative\v!leftpage }{\csname\??layoutmakeupalternative\v!page\endcsname}
+\setvalue{\??layoutmakeupalternative\v!rightpage}{\csname\??layoutmakeupalternative\v!page\endcsname}
\unexpanded\def\startpagelayout
{\bgroup
@@ -194,6 +210,6 @@
\def\page_layouts_start_layout[#1]#2\stoppagelayout
{\egroup
- \setvalue{\??layoutmethod#1}{#2}}
+ \setvalue{\??layoutmakeupalternative#1}{#2}}
\protect \endinput
diff --git a/tex/context/base/page-mis.lua b/tex/context/base/page-pst.lua
index 4f9d3c3e2..8586830cf 100644
--- a/tex/context/base/page-mis.lua
+++ b/tex/context/base/page-pst.lua
@@ -1,6 +1,6 @@
-if not modules then modules = { } end modules ['page-mis'] = {
+if not modules then modules = { } end modules ['page-pst'] = {
version = 1.001,
- comment = "companion to page-mis.mkiv",
+ comment = "companion to page-pst.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
@@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['page-mis'] = {
-- todo: adapt message
+local format, validstring = string.format, string.valid
local sortedkeys = table.sortedkeys
local cache = { }
@@ -16,7 +17,7 @@ local function flush(page)
local c = cache[page]
if c then
for i=1,#c do
- context.viafile(c[i])
+ context.viafile(c[i],format("page.%s",validstring(page,"nopage")))
end
cache[page] = nil
end
diff --git a/tex/context/base/page-mis.mkiv b/tex/context/base/page-pst.mkiv
index 6137bb462..7f8a39ca6 100644
--- a/tex/context/base/page-mis.mkiv
+++ b/tex/context/base/page-pst.mkiv
@@ -2,7 +2,7 @@
%D [ file=page-mis,
%D version=2008.11.17, % was part of page-flt.tex / 2000.10.20
%D title=\CONTEXT\ Page Macros,
-%D subtitle=Misc Float Things,
+%D subtitle=Postponing,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
@@ -11,9 +11,9 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\writestatus{loading}{ConTeXt Page Macros / Misc Float Things}
+\writestatus{loading}{ConTeXt Page Macros / Postponing}
-\registerctxluafile{page-mis}{1.001}
+\registerctxluafile{page-pst}{1.001}
\unprotect
@@ -21,8 +21,13 @@
\newevery\everytopofpage\relax
-\appendtoks \the\everytopofpage \to\everystarttext
-\appendtoks\global\everytopofpage\emptytoks\to\everystoptext
+\appendtoks
+ \the\everytopofpage
+\to \everystarttext
+
+\appendtoks
+ \global\everytopofpage\emptytoks
+\to \everystoptext
% \startpostponing [pagenumber] [+pageoffset]
%
@@ -44,8 +49,10 @@
%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.
-\newif \ifinpostponing % prevents nesting
-\newcount\c_page_postponed_blocks_next_page % set at the lua end
+%newif \ifinpostponing % prevents nesting
+
+\newcount \c_page_postponed_blocks_next_page % set at the lua end
+\newconditional\c_page_postponed_busy
\unexpanded\setvalue{\e!start\v!postponing}%
{\bgroup
@@ -65,11 +72,11 @@
\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)
+ \settrue\c_page_postponed_busy
+ \pagetotal\zeropoint % here? still needed? (was after flush pagefloats)
\the\everytopofpage\relax
%\flushrestfloats
- \doflushpagefloats
+ \page_floats_flush_page_floats
\setnormalcatcodes % postponing in verbatim
\restoreglobalbodyfont % otherwise problems inside split verbatim
\ctxcommand{flushpostponedblocks()}%
@@ -77,8 +84,8 @@
\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
+\unexpanded\def\page_postponed_blocks_flush
+ {\ifconditional\c_page_postponed_busy
% probably a nested flush
\else\ifnum\c_page_postponed_blocks_next_page=\zerocount
% nothing in cache
diff --git a/tex/context/base/page-run.mkiv b/tex/context/base/page-run.mkiv
index 62b1030ee..dabf37252 100644
--- a/tex/context/base/page-run.mkiv
+++ b/tex/context/base/page-run.mkiv
@@ -242,16 +242,16 @@ end
[\v!page]
[\c!frame=\v!on,
\c!corner=\v!rectangular,
- \c!frameoffset=\!!zeropoint,
- \c!framedepth=\!!zeropoint,
+ \c!frameoffset=\zeropoint,
+ \c!framedepth=\zeropoint,
\c!framecolor=layout:page]
\setupbackgrounds
[#1][#2]
[\c!background=,
\c!frame=\v!on,
\c!corner=\v!rectangular,
- \c!frameoffset=\!!zeropoint,
- \c!framedepth=\!!zeropoint,
+ \c!frameoffset=\zeropoint,
+ \c!framedepth=\zeropoint,
\c!framecolor=]
\else\iffirstargument
\showframe
diff --git a/tex/context/base/page-sel.mkiv b/tex/context/base/page-sel.mkiv
deleted file mode 100644
index 1e706aa22..000000000
--- a/tex/context/base/page-sel.mkiv
+++ /dev/null
@@ -1,347 +0,0 @@
-%D \module
-%D [ file=page-sel, % moved from page-imp
-%D version=1998.01.15,
-%D title=\CONTEXT\ Page Macros,
-%D subtitle=Page Selection,
-%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 will become runtime loaded code.
-
-\writestatus{loading}{ConTeXt Page Macros / Page Selection}
-
-\unprotect
-
-%D One can (mis)use this mechanism, in close cooperation
-%D with \PDFTEX\ to arrange pages of already produced files.
-%D
-%D \starttyping
-%D \insertpages[file.pdf][1,3][n=30,width=18cm]
-%D \stoptyping
-%D
-%D The pages are inserted in the text area, and even pages
-%D are repositioned according to the width. In this example
-%D empty pages are added after page 1 and 3.
-%D
-%D Selecting pages can be accomplished by:
-%D
-%D \starttyping
-%D \filterpages[file.pdf][1,3,5][n=30,width=18cm]
-%D \stoptyping
-%D
-%D One may pass \type {odd} or \type {even} instead of a
-%D comma separated list. A third alternative is:
-%D
-%D \starttyping
-%D \copypages[file.pdf][n=30,scale=950]
-%D \stoptyping
-%D
-%D This macros inserts the page, according to the settings
-%D provided.
-
-\def\insertpages
- {\dotripleempty\doinsertpages}
-
-\def\doinsertpages[#1][#2][#3]%
- {\doifassignmentelse{#2}
- {\dodoinsertpages[#1][][#2]}
- {\dodoinsertpages[#1][#2][#3]}}
-
-\def\dodoinsertpages[#1][#2][#3]%
- {\bgroup
- \dontcomplain
- \getfiguredimensions[#1]%
- \getparameters[\??ip][\c!n=\noffigurepages,\c!width=\!!zeropoint,#3]%
- \doifinset0{#2}{\emptyhbox\page}%
- \dorecurse\@@ipn
- {\dofilterpage{#1}\recurselevel
- \doifinset\recurselevel{#2}{\emptyhbox\page}}%
- \egroup}
-
-\def\filterpages
- {\dotripleempty\dofilterpages}
-
-\def\dofilterpages[#1][#2][#3]% % \noffigurepages not yet supported
- {\bgroup
- \dontcomplain
- \getfiguredimensions[#1]%
- \getparameters[\??ip][\c!n=\noffigurepages,\c!width=\!!zeropoint,#3]%
- \doifelse{#2}\v!even
- {\dorecurse\@@ipn
- {\ifodd\recurselevel\relax\else\dofilterpage{#1}\recurselevel\fi}}
- {\doifelse{#2}\v!odd
- {\dorecurse\@@ipn
- {\ifodd\recurselevel\relax\dofilterpage{#1}\recurselevel\fi}}
- {\def\dodocommand##1{\ifnum##1>\@@ipn\else\dofilterpage{#1}{##1}\fi}%
- \def\docommand ##1{\dowithrange{##1}\dodocommand}%
- \processcommalist[#2]\docommand}}%
- \egroup}
-
-\def\dofilterpage#1#2%
- {\hbox to \textwidth
- {\ifdoublesided\ifdim\@@ipwidth>\zeropoint\relax\ifodd\realpageno\else
- \hfill
- \def\dowithfigure{\hskip-\@@ipwidth}%
- \fi\fi\fi
- \setbox0\hbox
- {\externalfigure[#1][\c!page=#2,\c!height=\textheight]}%
- \wd0\zeropoint
- \box0}
- \page}
-
-\def\copypages
- {\dodoubleempty\docopypages}
-
-\def\docopypages[#1][#2]%
- {\bgroup
- \getfiguredimensions[#1]%
- \getparameters[\??ip]
- [\c!n=\noffigurepages,
- \c!marking=\v!off,
- \c!scale=\!!thousand,
- \c!offset=\!!zeropoint,
- #2]%
- \dorecurse\@@ipn
- {\vbox to \textheight
- {\hsize\textwidth
- \scratchdimen\@@ipoffset
- \centeredbox
- {\doifelse\@@ipmarking\v!on\cuthbox\hbox
- {\ifdim\scratchdimen>\zeropoint\relax
- \advance\vsize -2\scratchdimen
- \advance\hsize -2\scratchdimen
- \externalfigure[#1][\c!page=\recurselevel,#2,\c!scale=,\c!factor=\v!max,\c!offset=\v!overlay]%
- \else
- \externalfigure[#1][\c!page=\recurselevel,#2,\c!offset=\v!overlay]%
- \fi}}}
- \page}
- \egroup}
-
-%D \macros
-%D {combinepages}
-%D
-%D Yet another way of postprocessing is handles by \type
-%D {\combinepages}. This macro builds a matrix of pages from a
-%D file, for example:
-%D
-%D \starttyping
-%D \setuppapersize
-%D [A4][A4] % or [A4,landscape][A4,landscape]
-%D
-%D \setuplayout
-%D [header=0pt,footer=1cm,
-%D backspace=1cm,topspace=1cm,
-%D width=middle,height=middle]
-%D
-%D \setupfootertexts
-%D [presentation---\currentdate\space---\space\pagenumber]
-%D
-%D \starttext
-%D \combinepages[slides][nx=2,ny=3,frame=on]
-%D \stoptext
-%D \stoptyping
-%D
-%D One can influence the way the pages are combined. (This
-%D will be explained some time.)
-
-\def\combinepages
- {\dodoubleempty\docombinepages}
-
-\def\docombinepages[#1][#2]% a=perpag b=free
- {\bgroup
- \dontcomplain
- \getfiguredimensions[#1]%
- \getparameters
- [\??ip]
- [\c!alternative=\v!a,
- \c!n=\noffigurepages,\c!nx=2,\c!ny=2,\c!start=1,\c!stop=\!!maxcard,
- \c!distance=\bodyfontsize,
- \c!bottom=\vfill,\c!top=\vss,
- \c!left=\hss,\c!right=\hss,
- \c!before=\page,\c!after=\page,\c!inbetween=\blank,
- \c!frame=,\c!background=,\c!backgroundcolor=,
- #2]%
- \def\@@ipname{#1}%
- \@@ipbefore
- \expandcheckedcsname{\??ip::\c!alternative:}\@@ipalternative\v!b
- \@@ipafter
- \egroup}
-
-\setvalue{\??ip::\c!alternative:\v!a}%
- {\global\combinedpagescounter\@@ipstart
- \doloop
- {\vbox to \textheight
- {\hsize\textwidth % ? ?
- \scratchdimen\@@ipdistance
- \!!widtha \dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
- \!!heighta\dimexpr(\vsize-\@@ipny\scratchdimen+\scratchdimen)/\@@ipny\relax
- \dorecurse\@@ipny
- {\hbox to \hsize
- {\dorecurse\@@ipnx
- {\vbox to \!!heighta
- {\hsize\!!widtha
- \vsize\!!heighta
- \@@iptop
- \hbox to \hsize
- {\@@ipleft
- \ifnum\combinedpagescounter>\@@ipstop\relax
- \globallet\@@ipn\!!zerocount
- \else\ifnum\combinedpagescounter>\@@ipn \else
- \externalfigure[\@@ipname]
- [\c!object=\v!no,
- \c!page=\number\combinedpagescounter,
- \c!factor=\v!max,
- \c!background=\@@ipbackground,
- \c!backgroundcolor=\@@ipbackgroundcolor,
- \c!frame=\@@ipframe]%
- \fi\fi
- \@@ipright}
- \@@ipbottom}%
- \global\advance\combinedpagescounter\plusone
- \hfil}%
- \hfilneg}
- \vfil}%
- \vfilneg}%
- \page
- \ifnum\combinedpagescounter>\@@ipn \exitloop\fi}}
-
-\setvalue{\??ip::\c!alternative:\v!c}%
- {\global\combinedpagescounter\@@ipstart
- \doloop
- {\vbox to \textheight
- {\hsize\textwidth % ? ?
- \scratchdimen\@@ipdistance
- \!!widtha \dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
- \!!heighta\dimexpr(\vsize-\@@ipny\scratchdimen+\scratchdimen)/\@@ipny\relax
- \hbox to \hsize
- {\dorecurse\@@ipnx
- {\@@ipleft
- \vbox to \textheight
- {\hsize\!!widtha
- {\dorecurse\@@ipny
- {\@@iptop
- \hbox to \hsize
- {\vbox to \!!heighta
- {\hsize\!!widtha
- \vsize\!!heighta
- \ifnum\combinedpagescounter>\@@ipstop\relax
- \globallet\@@ipn\!!zerocount
- \else\ifnum\combinedpagescounter>\@@ipn \else
- \externalfigure[\@@ipname]
- [\c!object=\v!no,
- \c!page=\number\combinedpagescounter,
- \c!factor=\v!max,
- \c!background=\@@ipbackground,
- \c!backgroundcolor=\@@ipbackgroundcolor,
- \c!frame=\@@ipframe]%
- \fi\fi}}
- \global\advance\combinedpagescounter\plusone
- \@@ipbottom}%
- \vfil}%
- \vfilneg}
- \hfil}%
- \hfilneg}}
- \page
- \ifnum\combinedpagescounter>\@@ipn \exitloop\fi}}
-
-\setvalue{\??ip::\c!alternative:\v!horizontal}{\getvalue{\??ip::\c!alternative:\v!a}}
-\setvalue{\??ip::\c!alternative:\v!vertical }{\getvalue{\??ip::\c!alternative:\v!c}}
-
-\setvalue{\??ip::\c!alternative:\v!b}%
- {\global\combinedpagescounter\@@ipstart
- \doloop
- {\startbaselinecorrection
- \scratchdimen\@@ipdistance
- \!!widtha\dimexpr(\hsize-\@@ipnx\scratchdimen+\scratchdimen)/\@@ipnx\relax
- \hbox to \hsize
- {\dorecurse\@@ipnx
- {\global\advance\combinedpagescounter\plusone
- \ifnum\combinedpagescounter>\@@ipn \else
- \normalexpanded{\noexpand\externalfigure[\@@ipname]
- [\c!page=\number\combinedpagescounter,
- \c!width=\the\!!widtha,% todo \freezedimenmacro
- \c!background=\@@ipbackground,
- \c!backgroundcolor=\@@ipbackgroundcolor,
- \c!frame=\@@ipframe]}%
- \hfill
- \fi}\hfillneg}%
- \stopbaselinecorrection
- \ifnum\combinedpagescounter<\@@ipn\relax
- \@@ipinbetween
- \else
- \exitloop
- \fi}}
-
-% This macro cuts a page into n parts that can be pasted
-% together.
-
-\def\slicepages
- {\dotripleempty\doslicepages}
-
-\def\doslicepages[#1][#2][#3]%
- {\ifthirdargument
- \dodoslicepages[#1][#2][#3]%
- \else
- \dodoslicepages[#1][#2][#2]%
- \fi}
-
-\newcounter\slicedpagenumber
-
-\def\dodoslicepages[#1][#2][#3]%
- {\bgroup
- \dontcomplain
- \globallet\slicedpagenumber\!!zerocount
- \getfiguredimensions[#1]
- \getparameters
- [\??ip]
- [\c!n=1,
- \c!offset=\!!zeropoint,
- \c!hoffset=\!!zeropoint,\c!voffset=\!!zeropoint,
- \c!width=\figurewidth,\c!height=\figureheight,#2]
- \ifnum\@@ipn>\zerocount
- \definepapersize
- [\s!dummy][\c!height=\@@ipheight,\c!width=\@@ipwidth]
- \setuppapersize
- [\s!dummy][\s!dummy]
- \setuplayout
- [\c!backspace=\!!zeropoint,\c!topspace=\!!zeropoint,
- \c!height=\v!middle,\c!width=\v!middle,
- \c!textdistance=\!!zeropoint,
- \c!header=\!!zeropoint,\c!footer=\!!zeropoint]
- \fi
- \dorecurse\noffigurepages
- {\global\let\slicedpagenumber\recurselevel
- \ifnum\@@ipn>\plusone
- \dorecurse\@@ipn
- {\let\xslice\recurselevel
- \dorecurse\@@ipn
- {\let\yslice\recurselevel
- \clip
- [\c!nx=\@@ipn,\c!ny=\@@ipn,\c!x=\xslice,\c!y=\yslice]
- {\scale
- [\c!scale=\@@ipn000]
- {\externalfigure[#1][\c!page=\slicedpagenumber]}}
- \page}}
- \else
- \ifodd\slicedpagenumber\relax
- \getparameters[\??ip][#2]
- \else
- \getparameters[\??ip][#3]
- \fi
- \hskip\@@ipoffset
- \clip
- [\c!hoffset=\@@iphoffset,\c!voffset=\@@ipvoffset,
- \c!height=\@@ipheight,\c!width=\@@ipwidth]
- {\externalfigure[#1][\c!page=\slicedpagenumber]}
- \page
- \fi}
- \egroup}
-
-% \starttext \slicepages[slice1.pdf][n=3] \stoptext
-
-\protect \endinput
diff --git a/tex/context/base/page-sel.mkvi b/tex/context/base/page-sel.mkvi
new file mode 100644
index 000000000..1fe3f2f38
--- /dev/null
+++ b/tex/context/base/page-sel.mkvi
@@ -0,0 +1,368 @@
+%D \module
+%D [ file=page-sel, % moved from page-imp
+%D version=1998.01.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Selection,
+%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 code relates to old texexec features and one can wonder if it needs
+%D to be in the core. So, this could become runtime loaded code. Some of
+%D the alternatives need checking.
+
+\writestatus{loading}{ConTeXt Page Macros / Page Selection}
+
+\unprotect
+
+%D One can (mis)use this mechanism to (re)arrange pages of already produced
+%D files.
+%D
+%D \starttyping
+%D \insertpages[file.pdf][1,3][n=30,width=18cm]
+%D \stoptyping
+%D
+%D The pages are inserted in the text area, and even pages are repositioned
+%D according to the width. In this example empty pages are added after page
+%D 1 and 3.
+%D
+%D Selecting pages can be accomplished by:
+%D
+%D \starttyping
+%D \filterpages[file.pdf][1,3,5][n=30,width=18cm]
+%D \stoptyping
+%D
+%D One may pass \type {odd} or \type {even} instead of a comma separated list. A
+%D third alternative is:
+%D
+%D \starttyping
+%D \copypages[file.pdf][n=30,scale=950]
+%D \stoptyping
+%D
+%D This macros inserts the page, according to the settings provided.
+
+\installcorenamespace{withpages}
+
+\installsetuponlycommandhandler \??withpages {withpages}
+% \installdirectcommandhandler \??withpages {withpages}
+
+\newcount\c_page_selectors_n
+
+\unexpanded\def\insertpages
+ {\dotripleempty\page_selectors_insert}
+
+\def\page_selectors_insert[#filename][#emptylist][#settings]%
+ {\doifassignmentelse{#emptylist}
+ {\page_selectors_insert_indeed[#filename][][#emptylist]}
+ {\page_selectors_insert_indeed[#filename][#emptylist][#settings]}}
+
+\def\page_selectors_insert_indeed[#filename][#emptylist][#settings]%
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#filename]%
+ \global\c_page_selectors_n\noffigurepages\relax
+ \setupcurrentwithpages[\c!width=\zeropoint,#settings]%
+ \scratchwidth\directwithpagesparameter\c!width\relax
+ \doifinset0{#emptylist}
+ {\emptyhbox\page}%
+ \dorecurse\c_page_selectors_n
+ {\page_selectors_filter_a_page{#filename}\recurselevel
+ \doifinset\recurselevel{#emptylist}
+ {\emptyhbox\page}}%
+ \egroup}
+
+\unexpanded\def\filterpages
+ {\dotripleempty\page_selectors_filter}
+
+\def\page_selectors_filter[#filename][#selection][#settings]% % \noffigurepages not yet supported
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#filename]%
+ \global\c_page_selectors_n\noffigurepages\relax
+ \setupcurrentwithpages[\c!width=\zeropoint,#settings]%
+ \scratchwidth\directwithpagesparameter\c!width\relax
+ \edef\p_selection{#selection}%
+ \ifx\p_selection\v!even
+ \dorecurse\c_page_selectors_n
+ {\ifodd\recurselevel\else
+ \page_selectors_filter_a_page{#filename}\recurselevel
+ \fi}%
+ \else\ifx\p_selection\v!odd
+ \dorecurse\c_page_selectors_n
+ {\ifodd\recurselevel\relax
+ \page_selectors_filter_a_page{#filename}\recurselevel
+ \fi}%
+ \else
+ \def\page_selectors_filter_step_indeed#page%
+ {\ifnum#page>\c_page_selectors_n\else
+ \page_selectors_filter_a_page{#filename}{#page}%
+ \fi}%
+ \def\page_selectors_filter_step#step%
+ {\dowithrange{#step}\page_selectors_filter_step_indeed}%
+ \processcommacommand[\p_selection]\page_selectors_filter_step
+ \fi\fi
+ \egroup}
+
+\def\page_selectors_filter_a_page#filename#page%
+ {\hbox to \textwidth
+ {\ifdim\scratchwidth>\zeropoint
+ \rightorleftpageaction{\scratchwidth\zeropoint}{\hfill}%
+ \fi
+ \setbox\scratchbox\hbox
+ {\hskip-\scratchwidth
+ \externalfigure[#filename][\c!page=#page,\c!height=\textheight]\hss}%
+ \wd\scratchbox\zeropoint
+ \box\scratchbox}
+ \page}
+
+\unexpanded\def\copypages
+ {\dotripleempty\page_selectors_copy}
+
+\def\page_selectors_copy[#filename][#settings][#figuresettings]%
+ {\bgroup
+ \getfiguredimensions[#filename]%
+ \global\c_page_selectors_n\noffigurepages\relax
+ \setupcurrentwithpages[\c!marking=\v!off,\c!offset=\zeropoint,#settings]%
+ \scratchoffset\directwithpagesparameter\c!offset\relax
+ \dorecurse\c_page_selectors_n
+ {\vbox to \textheight
+ {\hsize\textwidth
+ \centeredbox
+ {\doifelse{\directwithpagesparameter\c!marking}\v!on\cuthbox\hbox % only place where cuthbox is used
+ {\ifdim\scratchoffset>\zeropoint\relax
+ \advance\vsize -2\scratchoffset
+ \advance\hsize -2\scratchoffset
+ \externalfigure[#filename][\c!page=\recurselevel,#figuresettings,\c!scale=,\c!factor=\v!max,\c!offset=\v!overlay]%
+ \else
+ \externalfigure[#filename][\c!page=\recurselevel,#figuresettings,\c!offset=\v!overlay]%
+ \fi}}}
+ \page}
+ \egroup}
+
+%D \macros
+%D {combinepages}
+%D
+%D Yet another way of postprocessing is handles by \type {\combinepages}. This macro
+%D builds a matrix of pages from a file, for example:
+%D
+%D \starttyping
+%D \setuppapersize
+%D [A4][A4] % or [A4,landscape][A4,landscape]
+%D
+%D \setuplayout
+%D [header=0pt,footer=1cm,
+%D backspace=1cm,topspace=1cm,
+%D width=middle,height=middle]
+%D
+%D \setupfootertexts
+%D [presentation---\currentdate\space---\space\pagenumber]
+%D
+%D \starttext
+%D \combinepages[slides][nx=2,ny=3,frame=on]
+%D \stoptext
+%D \stoptyping
+%D
+%D One can influence the way the pages are combined. (This will be explained some
+%D time.)
+
+\installcorenamespace{combinepagesalternative}
+
+\unexpanded\def\combinepages
+ {\dodoubleempty\page_selectors_combine}
+
+\def\page_selectors_combine[#filename][#settings]% a=perpag b=free
+ {\bgroup
+ \dontcomplain
+ \getfiguredimensions[#filename]%
+ \global\c_page_selectors_n\noffigurepages\relax
+ \setupcurrentwithpages
+ [\c!alternative=\v!a,
+ \c!nx=\plustwo,\c!ny=\plustwo,\c!start=\plusone,\c!stop=\maxcard,
+ \c!distance=\bodyfontsize,
+ \c!bottom=\vfill,\c!top=\vss,\c!left=\hss,\c!right=\hss,
+ \c!before=\page,\c!after=\page,\c!inbetween=\blank,
+ \c!frame=,\c!background=,\c!backgroundcolor=,
+ \c!name={#filename},
+ #settings]%
+ \directwithpagesparameter\c!before
+ \scratchnx\directwithpagesparameter\c!nx
+ \scratchny\directwithpagesparameter\c!ny
+ \scratchdistance\directwithpagesparameter\c!distance\relax
+ \scratchwidth\dimexpr(\textwidth-\scratchnx\scratchdistance+\scratchdistance)/\scratchnx\relax
+ \scratchheight\dimexpr(\textheight-\scratchny\scratchdistance+\scratchdistance)/\scratchny\relax
+ \expandcheckedcsname{\??combinepagesalternative}{\directwithpagesparameter\c!alternative}\v!b
+ \directwithpagesparameter\c!after
+ \egroup}
+
+\setvalue{\??combinepagesalternative\v!a}%
+ {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
+ \doloop
+ {\vbox to \textheight
+ {\dorecurse\scratchny
+ {\hbox to \textwidth
+ {\dorecurse\scratchnx
+ {\vbox to \scratchheight
+ {\hsize\scratchwidth
+ \vsize\scratchheight
+ \directwithpagesparameter\c!top
+ \hbox to \hsize
+ {\directwithpagesparameter\c!left
+ \ifnum\combinedpagescounter>\directwithpagesparameter\c!stop\relax
+ \global\c_page_selectors_n\zerocount
+ \else\ifnum\combinedpagescounter>\c_page_selectors_n \else
+ \externalfigure
+ [\directwithpagesparameter\c!name]
+ [\c!object=\v!no,
+ \c!page=\number\combinedpagescounter,
+ \c!factor=\v!max,
+ \c!background=\directwithpagesparameter\c!background,
+ \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
+ \c!frame=\directwithpagesparameter\c!frame]%
+ \fi\fi
+ \directwithpagesparameter\c!right}
+ \directwithpagesparameter\c!bottom}%
+ \global\advance\combinedpagescounter\plusone
+ \hfil}%
+ \hfilneg}
+ \vfil}%
+ \vfilneg}%
+ \page
+ \ifnum\combinedpagescounter>\c_page_selectors_n
+ \exitloop
+ \fi}}
+
+\setvalue{\??combinepagesalternative\v!c}%
+ {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
+ \doloop
+ {\vbox to \textheight
+ {\hbox to \textwidth
+ {\dorecurse\scratchnx
+ {\directwithpagesparameter\c!left
+ \vbox to \textheight
+ {\hsize\scratchwidth
+ \dorecurse\scratchny
+ {\directwithpagesparameter\c!top
+ \hbox to \hsize
+ {\vbox to \scratchheight
+ {\hsize\scratchwidth
+ \vsize\scratchheight
+ \ifnum\combinedpagescounter>\directwithpagesparameter\c!stop\relax
+ \global\c_page_selectors_n\zerocount
+ \else\ifnum\combinedpagescounter>\c_page_selectors_n \else
+ \externalfigure
+ [\directwithpagesparameter\c!name]
+ [\c!object=\v!no,
+ \c!page=\number\combinedpagescounter,
+ \c!factor=\v!max,
+ \c!background=\directwithpagesparameter\c!background,
+ \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
+ \c!frame=\directwithpagesparameter\c!frame]%
+ \fi\fi}}
+ \global\advance\combinedpagescounter\plusone
+ \directwithpagesparameter\c!bottom}}%
+ \hfil}%
+ \hfilneg}}%
+ \page
+ \ifnum\combinedpagescounter>\c_page_selectors_n
+ \exitloop
+ \fi}}
+
+\setvalue{\??combinepagesalternative\v!horizontal}{\getvalue{\??combinepagesalternative\v!a}}
+\setvalue{\??combinepagesalternative\v!vertical }{\getvalue{\??combinepagesalternative\v!c}}
+
+\setvalue{\??combinepagesalternative\v!b}%
+ {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
+ \doloop
+ {\startbaselinecorrection
+ \hbox to \textwidth
+ {\dorecurse\scratchnx
+ {\global\advance\combinedpagescounter\plusone
+ \ifnum\combinedpagescounter>\c_page_selectors_n \else
+ \normalexpanded{\externalfigure
+ [\directwithpagesparameter\c!name]
+ [\c!page=\number\combinedpagescounter,
+ \c!width=\the\scratchwidth,
+ \c!background=\directwithpagesparameter\c!background,
+ \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
+ \c!frame=\directwithpagesparameter\c!frame]}%
+ \hfill
+ \fi}%
+ \hfillneg}%
+ \stopbaselinecorrection
+ \ifnum\combinedpagescounter<\c_page_selectors_n\relax
+ \directwithpagesparameter\c!inbetween
+ \else
+ \exitloop
+ \fi}}
+
+% This macro cuts a page into n parts that can be pasted together.
+
+\unexpanded\def\slicepages
+ {\dotripleempty\page_selectors_slice}
+
+\def\page_selectors_slice[#filename][#oddsettings][#evensettings]%
+ {\ifthirdargument
+ \page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]%
+ \else
+ \page_selectors_slice_indeed[#filename][#oddsettings][#oddsettings]%
+ \fi}
+
+\let\slicedpagenumber\!!zerocount
+\let\slicedpagestepx \!!zerocount
+\let\slicedpagestepy \!!zerocount
+
+\def\page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]%
+ {\bgroup
+ \dontcomplain
+ \global\let\slicedpagenumber\!!zerocount
+ \getfiguredimensions[#filename]%
+ \global\c_page_selectors_n\noffigurepages\relax
+ \setupcurrentwithpages
+ [\c!offset=\zeropoint,\c!hoffset=\zeropoint,\c!voffset=\zeropoint,
+ \c!width=\figurewidth,\c!height=\figureheight,#oddsettings]%
+ \ifnum\c_page_selectors_n>\zerocount
+ \definepapersize
+ [\s!dummy][\c!height=\directwithpagesparameter\c!height,\c!width=\directwithpagesparameter\c!width]%
+ \setuppapersize
+ [\s!dummy][\s!dummy]%
+ \setuplayout
+ [\c!backspace=\zeropoint,\c!topspace=\zeropoint,
+ \c!height=\v!middle,\c!width=\v!middle,
+ \c!textdistance=\zeropoint,
+ \c!header=\zeropoint,\c!footer=\zeropoint]%
+ \fi
+ \dorecurse\noffigurepages
+ {\global\let\slicedpagenumber\recurselevel
+ \ifnum\c_page_selectors_n>\plusone
+ \dorecurse\c_page_selectors_n
+ {\let\slicedpagestepx\recurselevel
+ \dorecurse\c_page_selectors_n
+ {\let\slicedpagestepy\recurselevel
+ \clip
+ [\c!nx=\c_page_selectors_n,\c!ny=\c_page_selectors_n,\c!x=\slicedpagestepx,\c!y=\slicedpagestepy]
+ {\scale
+ [\c!scale=\number\c_page_selectors_n000]
+ {\externalfigure[#filename][\c!page=\slicedpagenumber]}}%
+ \page}}%
+ \else
+ \ifodd\slicedpagenumber\relax
+ \setupcurrentwithpages[#oddsettings]%
+ \else
+ \setupcurrentwithpages[#evensettings]%
+ \fi
+ \hskip\directwithpagesparameter\c!offset\relax
+ \clip
+ [\c!hoffset=\directwithpagesparameter\c!hoffset,\c!voffset=\directwithpagesparameter\c!voffset,
+ \c!height=\directwithpagesparameter\c!height,\c!width=\directwithpagesparameter\c!width]
+ {\externalfigure[#filename][\c!page=\slicedpagenumber]}%
+ \page
+ \fi}
+ \egroup}
+
+% \starttext \slicepages[slice1.pdf][n=3] \stoptext
+
+\protect \endinput
diff --git a/tex/context/base/page-set.mkiv b/tex/context/base/page-set.mkiv
index 467f22493..45755436e 100644
--- a/tex/context/base/page-set.mkiv
+++ b/tex/context/base/page-set.mkiv
@@ -13,7 +13,9 @@
% getnoflines vs getrawnoflines
-% some day: cleanup and go etex
+% This is a rather old mechanism and we can best keep it as it is. If it gets
+% replaced by a more modern solution, it will be an extra mechanism. So, we
+% only do some basic cleanup.
\writestatus{loading}{ConTeXt Page Macros / Column Sets}
@@ -44,13 +46,95 @@
\newif\ifenoughcolumncells
\newif\ifsomefreecolumncells
\newif\ifcolumnspread
-\newif\iftracecolumnset % \tracecolumnsettrue
+\newif\iftracecolumnset
+
+\newif\ifforcecolumnsetgrid \forcecolumnsetgridtrue
+\newif\ifcollectingsetcontent % never set
+\newif\ifcarryoverfootnotes %\carryoverfootnotestrue
+\newif\iflastcolumnfootnotes % never set \lastcolumnfootnotestrue
+\newif\ifintermediatefootnotes
+
+\newbox \b_page_set_preceding
+\newbox \b_page_set_trailing
+
+\newdimen \d_page_set_local_hsize
+\newconditional\c_page_set_width_set
+
+\installcorenamespace{columnsetgrid}
\def\columnmaxcells {75} % runtime
\def\columnmaxfreecells {0} % runtime
\def\columngaplimit {0} % {5}
-\def\@otr@{otr}
+\def\page_set_cell #1#2{\csname \??columnsetgrid:\number#1:\number#2\endcsname}
+\def\page_set_cell_get#1#2{\box\csname \??columnsetgrid:\number#1:\number#2\endcsname}
+\def\page_set_cell_set#1#2{\global\setbox\csname\??columnsetgrid:\number#1:\number#2\endcsname}
+
+\def\page_set_cell_doifelse#1#2%
+ {\relax
+ \ifvoid\csname\??columnsetgrid:\number#1:\number#2\endcsname
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\page_set_cell_erase_grid % maybe dedicated loops ... make another loop when max's have changed
+ {\bgroup
+ \increment\columnmaxcells\relax
+ \ifodd\realpageno \else
+ \columnspreadfalse
+ \fi
+ \ifcolumnspread
+ \page_set_cell_erase_grid_spread
+ \else
+ \page_set_cell_erase_grid_page
+ \fi
+ \page_set_cell_erase_grid_top
+ \global\columnfirstcell\zerocount
+ \global\columnlastcell \columnfirstcell
+ \global\columnfreecells\columnfirstcell
+ \egroup}
+
+\let\m_page_column_l\relax
+\let\m_page_column_r\relax
+
+\def\page_set_cell_erase_grid_spread
+ {\dorecurse\nofcolumns
+ {\let \m_page_column_l\recurselevel
+ \edef\m_page_column_r{\the\numexpr\recurselevel+\lofcolumns}%
+ \dostepwiserecurse \zerocount \columnmaxcells \plusone
+ {\ifcsname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \ifcsname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \box\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \else
+ \emptyhbox
+ \expandafter\newbox\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \fi
+ \else
+ \expandafter\newbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \ifcsname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname\box\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \else
+ \expandafter\newbox\csname\??columnsetgrid:\m_page_column_r:\recurselevel\endcsname
+ \fi
+ \fi}}}
+
+\def\page_set_cell_erase_grid_page
+ {\dorecurse \tofcolumns
+ {\let\m_page_column_l\recurselevel
+ \dostepwiserecurse \zerocount \columnmaxcells \plusone
+ {\ifcsname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \global\setbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname\emptybox
+ \else
+ \expandafter\newbox\csname\??columnsetgrid:\m_page_column_l:\recurselevel\endcsname
+ \fi}}}
+
+\def\page_set_cell_erase_grid_top
+ {\dorecurse\tofcolumns
+ {\global\setbox\csname\??columnsetgrid:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}}
+
+% % % %
\def\OTRSETmakeupwidth{\innermakeupwidth}
@@ -60,15 +144,6 @@
\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}
-\def\OTRSETsetgridcell#1#2{\global\setbox\csname\@otr@:\number#1:\number#2\endcsname}
-
-\long\def\OTRSETdoifcellelse#1#2%
- {\relax\ifvoid\csname\@otr@:\number#1:\number#2\endcsname
- \@EA\secondoftwoarguments\else\@EA\firstoftwoarguments
- \fi}
-
% The following two macros are used to compensate for a switch in body fonts
% as in:
%
@@ -184,64 +259,16 @@
\relax % needed ! ! ! ! else lookahead over \fi and \@EA
\@EA\egroup\@EA\scratchdimen\the\!!dimena\relax}
-\def\columnerasegridboxes % maybe dedicated loops
- {\bgroup
- \increment\columnmaxcells\relax
- \ifodd\realpageno
- \else % we are on the other page
- \columnspreadfalse
- \fi
- \ifcolumnspread
- \dorecurse\nofcolumns
- {\let\!!stringa\recurselevel
- \scratchcounter\recurselevel \advance\scratchcounter\lofcolumns
- \edef\!!stringb{\the\scratchcounter}%
- \dostepwiserecurse \zerocount \columnmaxcells \plusone
- {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname
- \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
- \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname
- \box\csname\@otr@:\!!stringb:\recurselevel\endcsname
- %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
- \else
- \emptyhbox
- %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\emptybox
- \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
- \fi
- \else
- \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
- \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname
- \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
- \else
- \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
- \fi
- \fi}}%
- \else
- \dorecurse \tofcolumns
- {\let\!!stringa\recurselevel
- \dostepwiserecurse \zerocount \columnmaxcells \plusone
- {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname
- \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\emptybox
- \else
- \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
- \fi}}%
- \fi
- \dorecurse\tofcolumns
- {\global\setbox\csname\@otr@:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}%
- \global\columnfirstcell\zerocount
- \global\columnlastcell\columnfirstcell
- \global\columnfreecells\columnfirstcell
- \egroup}
-
\def\doOTRSETsetgridcells#1#2#3#4#5#6% placeholder col row wid hei {data}
{\!!countd#2\advance\!!countd#4\advance\!!countd\minusone
\!!counte#3\advance\!!counte#5\advance\!!counte\minusone
\dostepwiserecurse{#2}\!!countd\plusone
{\!!countf\recurselevel
\dostepwiserecurse{#3}\!!counte\plusone
- {\OTRSETsetgridcell\!!countf\recurselevel#1}}%
+ {\page_set_cell_set\!!countf\recurselevel#1}}%
\dostepwiserecurse{#3}\!!counte\plusone
- {\wd\OTRSETgridcell{#2}\recurselevel\hsize}%
- \OTRSETsetgridcell{#2}\!!counte#6}
+ {\wd\page_set_cell{#2}\recurselevel\hsize}%
+ \page_set_cell_set{#2}\!!counte#6}
\def\OTRSETsetgridcells
{\doOTRSETsetgridcells{\copy\placeholderboxb}}
@@ -252,19 +279,17 @@
\unexpanded\def\setupcolumnsetlines{\doquintupleempty\dosetupcolumnsettrick[l]}
\unexpanded\def\setupcolumnsetstart{\doquintupleempty\dosetupcolumnsettrick[s]}
+\installcorenamespace{columnsettag} % temp hack
+
\def\dosetupcolumnsettrick[#1][#2][#3][#4][#5]% tag id page col value
- {% not needed, is already relative
- % \doifinstringelse{+}{#3}{\scratchcounter\realpageno}{\scratchcounter\zerocount}%
- % \advance\scratchcounter#3\relax % \relax needed
- % \setevalue{\??mc:#1:#2:\the\scratchcounter:\number#4}{\number#5}}
- \iffifthargument
- \setevalue{\??mc:#1:#2:\number#3:\number#4}{\number#5}%
+ {\iffifthargument
+ \setevalue{\??columnsettag:#1:#2:\number#3:\number#4}{\number#5}%
\else
- \setevalue{\??mc:#1:#2:\number#3:0}{\number#4}%
+ \setevalue{\??columnsettag:#1:#2:\number#3:0}{\number#4}%
\fi}
-\def\currentcolumnmaxcellstag #1{\??mc:l:\OTRSETidentifier:\columnsetpage:\number#1}
-\def\currentcolumnstartcelltag#1{\??mc:s:\OTRSETidentifier:\columnsetpage:\number#1}
+\def\currentcolumnmaxcellstag #1{\??columnsettag:l:\OTRSETidentifier:\columnsetpage:\number#1}
+\def\currentcolumnstartcelltag#1{\??columnsettag:s:\OTRSETidentifier:\columnsetpage:\number#1}
\def\doresetcolumnsetlines#1%
{\ifcsname\currentcolumnmaxcellstag{#1}\endcsname
@@ -312,7 +337,7 @@
{\ifnum\columnfirstcell>\columnmaxcells\relax
\exitloop
\else
- \OTRSETdoifcellelse{#1}\columnfirstcell
+ \page_set_cell_doifelse{#1}\columnfirstcell
{\global\advance\columnfirstcell\plusone}\exitloop
\fi}%
\global\columnlastcell\columnfirstcell
@@ -320,7 +345,7 @@
{\ifnum\columnlastcell>\columnmaxcells\relax
\exitloop
\else
- \OTRSETdoifcellelse{#1}\columnlastcell
+ \page_set_cell_doifelse{#1}\columnlastcell
{\global\advance\columnlastcell \minusone \exitloop}
{\global\advance\columnlastcell \plusone }%
\fi}%
@@ -351,7 +376,7 @@
\edef\columnmaxcells{\the\scratchcounter}%
\scratchcounter\zerocount
\dostepwiserecurse{#2}\columnmaxcells\plusone
- {\OTRSETdoifcellelse{#1}\recurselevel
+ {\page_set_cell_doifelse{#1}\recurselevel
{\ifnum\columnmaxfreecells<\scratchcounter
\edef\columnmaxfreecells{\the\scratchcounter}%
\let\columnfrmfreecells\recurselevel
@@ -362,7 +387,7 @@
\long\def\OTRSETrecurseRL#1%
{\dostepwiserecurse\nofcolumns\plusone\minusone
- {#1\hskip\OTRSETgetparameter\c!distance\recurselevel}}
+ {#1\hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}}
\def\OTRSETmakegridbox
{\ifcase\columndirection
@@ -373,6 +398,28 @@
\def\OTRSETmakeupwidth{\makeupwidth} % temporary indirectness
+\def\page_set_make_background_box
+ {\begingroup
+ \mofcolumns\recurselevel % used to signal mp
+ \d_page_set_local_hsize\OTRSETlocalwidth\recurselevel
+ \scratchdistance\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance\relax
+ \edef\currentcolumnset{\currentcolumnset:\recurselevel}%
+ \letcolumnsetparameter\c!width \d_page_set_local_hsize
+ \letcolumnsetparameter\c!height\!!heighta
+ \letcolumnsetparameter\c!lines \empty
+ \letcolumnsetparameter\c!region\currentcolumnset
+ \setbox\scratchbox\hbox\inheritedcolumnsetframed{}% maybe \fastlocalframed
+ \wd\scratchbox\d_page_set_local_hsize
+ \ht\scratchbox\!!heighta
+ \ifcase\columndirection
+ \hskip\scratchdistance
+ \box\scratchbox
+ \else
+ \box\scratchbox
+ \hskip\scratchdistance
+ \fi
+ \endgroup}
+
\def\OTRSETdomakegridbox#1#2#3%
{\hbox\bgroup
\dontcomplain
@@ -380,28 +427,13 @@
\!!heighta \textheight
% test first !
\hbox to \OTRSETmakeupwidth
- {\dostepwiserecurse{#1}{#2}{#3}
- {\mofcolumns\recurselevel
- \localcolumnwidth\OTRSETlocalwidth\mofcolumns
- \setbox\scratchbox\hbox\localframed
- [\??mc\OTRSETidentifier\number\mofcolumns]%
- [\c!width=\localcolumnwidth,\c!height=\!!heighta,\c!lines=]%
- {}%
- \wd\scratchbox\localcolumnwidth
- \ht\scratchbox\!!heighta
- \ifcase\columndirection
- \hskip\OTRSETgetparameter\c!distance\recurselevel
- \box\scratchbox
- \else
- \box\scratchbox
- \hskip\OTRSETgetparameter\c!distance\recurselevel
- \fi}}%
+ {\dostepwiserecurse{#1}{#2}{#3}\page_set_make_background_box}%
\hskip-\OTRSETmakeupwidth
% main text
\hbox to \OTRSETmakeupwidth
{\dostepwiserecurse{#1}{#2}{#3}
{\mofcolumns\recurselevel
- \localcolumnwidth\OTRSETlocalwidth\mofcolumns
+ \d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
\offinterlineskip
\setbox\scratchbox\vbox to \!!heighta
{%\topskipcorrection % not needed
@@ -417,14 +449,14 @@
\vfill
\fi
\dorecurse\columnmaxcells
- {\setbox\scratchbox\hbox{\OTRSETgetgridcell\mofcolumns\recurselevel}%
+ {\setbox\scratchbox\hbox{\page_set_cell_get\mofcolumns\recurselevel}%
\ht\scratchbox\strutht
\dp\scratchbox\strutdp
\ifcase\columndirection
\box\scratchbox
\else
- \hbox to \localcolumnwidth
- {\hskip\localcolumnwidth\llap{\box\scratchbox}}%
+ \hbox to \d_page_set_local_hsize
+ {\hskip\d_page_set_local_hsize\llap{\box\scratchbox}}%
\fi
\par}%
\ifcase\OTRSETbalancemethod
@@ -439,12 +471,12 @@
\kern\zeropoint
\vss
\fi}%
- \wd\scratchbox\localcolumnwidth % \textwidth
+ \wd\scratchbox\d_page_set_local_hsize % \textwidth
\page_marks_synchronize_column{#1}{#2}\recurselevel\scratchbox
\ifcase\columndirection
- \hskip\OTRSETgetparameter\c!distance\recurselevel\box\scratchbox
+ \hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance\box\scratchbox
\else
- \box\scratchbox\hskip\OTRSETgetparameter\c!distance\recurselevel
+ \box\scratchbox\hskip\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance
\fi}}%
\egroup}
@@ -459,7 +491,7 @@
\!!counta\columnmaxcells
\donetrue
\doloop
- {\dorecurse\nofcolumns{\OTRSETdoifcellelse\recurselevel\!!counta\donefalse\donothing}%
+ {\dorecurse\nofcolumns{\page_set_cell_doifelse\recurselevel\!!counta\donefalse\donothing}%
\ifdone
\ifnum\!!counta>\plusone\advance\!!counta\minusone\else\exitloop\fi
\else
@@ -483,22 +515,22 @@
{\placebottomnotes}%
\ifdim\ht\scratchbox>\zeropoint
\setbox\scratchbox\hbox
- {\hbox to \zeropoint{\OTRSETgetgridcell\nofcolumns\lastcolumnlastcell}%
+ {\hbox to \zeropoint{\page_set_cell_get\nofcolumns\lastcolumnlastcell}%
\box\scratchbox}%
\ht\scratchbox\strutht
\dp\scratchbox\strutdp
- \OTRSETsetgridcell\nofcolumns\lastcolumnlastcell\box\scratchbox
+ \page_set_cell_set\nofcolumns\lastcolumnlastcell\box\scratchbox
\fi
\global\lastcolumnlastcell\zerocount
\fi}
\def\OTRSETdoflush
- {\ifcollectingcontent
+ {\ifcollectingsetcontent
\global\mofcolumns\plusone
\else
\OTRSETdofinalflush
\OTRSETdofinaloutput
- \ifnum\columnsetpage>0
+ \ifnum\columnsetpage>\zerocount
\dorecurse\nofcolumns{\doresetcolumnsetlines\recurselevel}%
\fi
\doglobal\increment\columnsetpage
@@ -554,11 +586,10 @@
\newdimen \OTRSETtextsheight
\let \OTRSETidentifier=\empty
-\def\OTRSETgetparameter#1#2{\csname\??mc\OTRSETidentifier\number#2#1\endcsname}
-\def\OTRSETsetparameter#1#2{\setvalue{\??mc\OTRSETidentifier\number#2#1}}
-
\def\OTRSETskipstart
- {\scratchcounter\executeifdefined{\??mc\OTRSETidentifier\c!start}\zerocount
+ {\doifelsenothing{\columnsetparameter\c!start}
+ {\scratchcounter\zerocount}%
+ {\scratchcounter\columnsetparameter\c!start}%
\relax % needed !
\ifcase\scratchcounter\else
\advance\scratchcounter\plusone
@@ -569,7 +600,7 @@
\fi}
\unexpanded\def\page_set_command_set_vsize % snap per sectie (gap here?)
- {\ifcollectingcontent \else % can be assigndimen
+ {\ifcollectingsetcontent \else % can be assigndimen
\OTRSETsetcolumnmaxcells % layout can be changed
\OTRSETskipstart % not that well tested
\OTRSETcheckinsert % added
@@ -577,7 +608,7 @@
\ifsomefreecolumncells
\global\vsize\columnfreecells\lineheight
\ifinotr % else problems with floats, see extreme
- \global\pagegoal\vsize % niet nodig, tenzij binnen otr
+ \pagegoal\vsize % niet nodig, tenzij binnen otr
\fi
\synchronizeoutput % fails on example
% \allowbreak % hm
@@ -586,12 +617,12 @@
\fi}
\def\page_set_command_set_hsize % of course this does not migrate outside the otr
- {\localcolumnwidth\OTRSETlocalwidth\mofcolumns
- \textwidth\localcolumnwidth
- \hsize\localcolumnwidth}
+ {\d_page_set_local_hsize\OTRSETlocalwidth\mofcolumns
+ \textwidth\d_page_set_local_hsize
+ \hsize\d_page_set_local_hsize}
\unexpanded\def\page_set_command_synchronize_hsize
- {\ifcase0\getvalue{\??mc\??mc\c!width}\else % some width set
+ {\ifconditional\c_page_set_width_set
\bgroup
\scratchdimen\OTRSETlocalwidth\mofcolumns
\ifdim\scratchdimen=\textwidth
@@ -829,7 +860,7 @@
{\ifnum\columngaplimit>\zerocount
\donefalse
\dostepwiserecurse{#2}\columnmaxcells\plusone
- {\OTRSETdoifcellelse{#1}\recurselevel
+ {\page_set_cell_doifelse{#1}\recurselevel
{\ifdone
\!!countb\recurselevel \advance\!!countb -\!!counta\relax
\ifnum\!!countb>\plusone
@@ -837,7 +868,7 @@
\ifnum\!!countb<\columngaplimit\relax
\!!countb\recurselevel \advance\!!countb \minusone
\dostepwiserecurse\!!counta\!!countb\plusone
- {\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}%
+ {\page_set_cell_set{#1}\recurselevel\copy\placeholderboxc}%
%\message{[gap]}%
\fi
\fi
@@ -951,7 +982,7 @@
\else
\advance\columnhcells \plusone
\advance\scratchcounter \plusone
- \advance\totalcolumnspace \OTRSETgetparameter\c!distance\scratchcounter
+ \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\number\scratchcounter}\c!distance
\fi
\else
\exitloop
@@ -973,9 +1004,9 @@
%\scratchcounter#2\advance\scratchcounter\minusone
%\ifnum\scratchcounter>0
% \dostepwiserecurse{#1}\!!countd\plusone
-% {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% {\ifdim\wd\page_set_cell\recurselevel\scratchcounter>\zeropoint
% \let\columnspacetopoffset\plusone
-% \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \else\ifdim\dp\page_set_cell\recurselevel\scratchcounter>\zeropoint
% \let\columnspacetopoffset\plusone
% \fi\fi}%
% \advance\!!counte \columnspacetopoffset \relax
@@ -986,9 +1017,9 @@
%\advance\scratchcounter \columnvcells \relax
%\ifnum\scratchcounter>\columnmaxcells\else
% \dostepwiserecurse{#1}\!!countd\plusone
-% {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% {\ifdim\wd\page_set_cell\recurselevel\scratchcounter>\zeropoint
% \let\columnspacebotoffset\plusone
-% \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
+% \else\ifdim\dp\page_set_cell\recurselevel\scratchcounter>\zeropoint
% \let\columnspacebotoffset\plusone
% \fi\fi}%
% \advance\!!counte \columnspacebotoffset \relax
@@ -999,12 +1030,15 @@
\!!countf\recurselevel\relax
\dostepwiserecurse{#2}\!!counte\plusone % rows
{\ifenoughcolumncells
- \OTRSETdoifcellelse\!!countf\recurselevel
+ \page_set_cell_doifelse\!!countf\recurselevel
{\enoughcolumncellsfalse}{}%
\fi}%
\fi}%
\fi}
+\let\preferedcolumn\empty
+\let\preferedrow \empty
+
\def\OTRSETsetpreferedcolumnslot#1#2%
{\doifsomething{#1}{\edef\preferedcolumn{#1}}%
\doifsomething{#2}{\edef\preferedrow {#2}}}
@@ -1078,7 +1112,7 @@
\def\OTRSETstoreincolumnslotFXTB#1% fixed column
{\OTRSETcheckprefered
- \OTRSETdoifcellelse\pofcolumns\plusone
+ \page_set_cell_doifelse\pofcolumns\plusone
{\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot1}{#1}% % 1/2 dependent of place, todo
\OTRSETflushtextsofar
\OTRSETstoreincolumnslotindeed
@@ -1087,7 +1121,7 @@
\def\OTRSETstoreincolumnslotFXBT#1% fixed column
{\OTRSETcheckprefered
- \OTRSETdoifcellelse\pofcolumns\columnmaxcells
+ \page_set_cell_doifelse\pofcolumns\columnmaxcells
{\OTRSETprepareforcolumnslot2}{\OTRSETprepareforcolumnslot3}{#1}% % 3/2 dependent of place, todo
\OTRSETflushtextsofar
\OTRSETstoreincolumnslotindeed
@@ -1264,7 +1298,7 @@
\fi}
\unexpanded\def\page_set_command_check_if_float_fits
- {\global\ifnofloatpermitted\roomforfloatfalse\else\roomforfloattrue\fi}
+ {\global\ifconditional\c_page_floats_not_permitted\setfalse\c_page_floats_room\else\settrue\c_page_floats_room\fi}
\def\OTRSETunpreparebox#1%
{\ifhbox#1% spans and so
@@ -1279,25 +1313,25 @@
\def\OTRSETsavebox#1% clean up the skips
{\OTRSETunpreparebox{#1}%
- \dofloatssave\s!text}
+ \page_floats_save\s!text}
\def\OTRSETresavebox#1% clean up the skips
{\OTRSETunpreparebox{#1}%
- \dofloatsresave\s!text}
+ \page_floats_resave\s!text}
\unexpanded\def\page_set_command_flush_float_box
- {\iftestfloatbox\ruledhbox\fi{\box\floatbox}}
+ {\box\floatbox}
\unexpanded\def\page_set_command_flush_floats
{\bgroup
\def\OTRSETsavebox##1{\!!doneafalse}%
\doloop
- {\ifsomefloatwaiting
+ {\ifconditional\c_page_floats_some_waiting
\OTRSETskipstart
- \dofloatsgetinfo\s!text
+ \page_floats_get_info\s!text
\ifdim\floatwidth>\zeropoint
\!!doneatrue
- \dofloatsflush\s!text{1}%
+ \page_floats_flush\s!text\plusone
\dp\floatbox\zeropoint
\OTRSETstoreincolumnslot{TBLR}\floatbox
\if!!donea
@@ -1333,9 +1367,9 @@
\else
% only span if there is a next column with content
\dorecurse\columnmaxcells
- {\ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
+ {\ifdim\ht\page_set_cell\currenthcell\currentvcell>\zeropoint
\centergridcellonlyfalse
- \else\ifdim\dp\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
+ \else\ifdim\dp\page_set_cell\currenthcell\currentvcell>\zeropoint
\centergridcellonlyfalse
\fi\fi}%
\fi
@@ -1343,10 +1377,10 @@
\currenthcell\recurselevel
\dorecurse\columnmaxcells
{\currentvcell\recurselevel\relax
- \ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
- \ifdim\dp\OTRSETgridcell\currenthcell\currentvcell=\zeropoint
+ \ifdim\ht\page_set_cell\currenthcell\currentvcell>\zeropoint
+ \ifdim\dp\page_set_cell\currenthcell\currentvcell=\zeropoint
\bgroup
- \setbox\scratchbox\OTRSETgetgridcell\currenthcell\currentvcell
+ \setbox\scratchbox\page_set_cell_get\currenthcell\currentvcell
\getnoflines{\ht\scratchbox}%
\!!counta\currentvcell
\advance\!!counta -\noflines
@@ -1363,9 +1397,9 @@
{\if!!doneb
\let\xrecurselevel\recurselevel
\dostepwiserecurse\!!counta\currentvcell\plusone
- {\ifdim\ht\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint
+ {\ifdim\ht\page_set_cell\xrecurselevel\recurselevel>\zeropoint
\!!donebfalse
- \else\ifdim\wd\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint
+ \else\ifdim\wd\page_set_cell\xrecurselevel\recurselevel>\zeropoint
\!!donebfalse
\fi\fi}%
\if!!doneb
@@ -1375,11 +1409,11 @@
\totalcolumnspace\OTRSETlocalwidth\currenthcell
\dostepwiserecurse\!!countc\!!countb\plusone
{\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel
- \advance\totalcolumnspace \OTRSETgetparameter\c!distance\recurselevel}%
+ \advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
\ifdim\totalcolumnspace>\wd\scratchbox
\setbox\scratchbox\hbox to \totalcolumnspace{\hss\box\scratchbox\hss}%
\fi
- \OTRSETsetgridcell\currenthcell\currentvcell\box\scratchbox
+ \page_set_cell_set\currenthcell\currentvcell\box\scratchbox
\egroup
\fi
\fi}}%
@@ -1388,8 +1422,8 @@
\def\OTRSETinitializecolumns% once per page
{\columnspreadtrue % todo
\ifcolumnspread
- \global\rofcolumns\getvalue{\??mc\OTRSETidentifier\c!nright}%
- \global\lofcolumns\getvalue{\??mc\OTRSETidentifier\c!nleft}%
+ \global\rofcolumns\columnsetparameter\c!nright
+ \global\lofcolumns\columnsetparameter\c!nleft
\global\tofcolumns\rofcolumns \relax
\ifodd\realpageno\relax
\global\nofcolumns\rofcolumns
@@ -1398,67 +1432,70 @@
\global\nofcolumns\lofcolumns
\fi
\else
- \global\nofcolumns\getvalue{\??mc\OTRSETidentifier\c!n}%
+ \global\nofcolumns\columnsetparameter\c!n
\global\rofcolumns\nofcolumns
\global\lofcolumns\nofcolumns
\global\tofcolumns\nofcolumns
\fi
\OTRSETassignwidths
\global\mofcolumns\plusone
- \columnerasegridboxes}
+ \page_set_cell_erase_grid}
-% vanaf hier:
-
-\unexpanded\def\definecolumnset
- {\dodoubleargument\dodefinecolumnset}
-
-\def\dodefinecolumnset[#1][#2]%
- {\getparameters[\??mc#1]
- [\c!direction=\v!right,
- \c!balance=\v!no,
- \c!distance=1.5\bodyfontsize, % controleren
- \c!n=2,
- \c!nleft=\getvalue{\??mc#1\c!n},
- \c!nright=\getvalue{\??mc#1\c!n},
- \c!width=\v!fit,
- \c!lines=0,
- \c!start=0,
- #2]%
- \dorecurse{\getvalue{\??mc#1\c!nleft}} % todo
- {\dododefinecolumnset[#1][\recurselevel]}%
- \dorecurse{\getvalue{\??mc#1\c!nright}} % todo
- {\dododefinecolumnset[#1][\recurselevel]}%
- % redo framed settings
- \setupcolumnset[#1][1][\c!distance=\!!zeropoint]}
-
-\def\dododefinecolumnset[#1][#2]%
- {\presetlocalframed
- [\??mc#1#2]%
- \setupcolumnset
- [#1][#2]
- [\c!offset=\v!overlay,
- \c!frame=\v!off,
- \c!align=,
- \c!lines=0,% really needed since c!regels is now part of framed
- \c!width=\getvalue{\??mc#1\c!width},
- \c!distance=\getvalue{\??mc#1\c!distance}]}
+% this is a first step in upgrading
+
+\installcorenamespace{columnset}
+
+\installframedcommandhandler \??columnset {columnset} \??columnset
+
+\setupcolumnset % todo, use the rather basic backgroundframed
+ [\c!direction=\v!right,
+ \c!balance=\v!no,
+ \c!distance=1.5\bodyfontsize,
+ \c!n=2,
+ \c!nleft=\columnsetparameter\c!n,
+ \c!nright=\columnsetparameter\c!n,
+ \c!width=\v!fit,
+ \c!lines=0,
+ \c!start=0,
+ \c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!align=,
+ \c!lines=0]
+
+\let\page_set_setup_saved\setupcolumnset
+
+\newconditional\c_page_set_defining
+
+\appendtoks
+ \ifconditional\c_page_set_defining \else
+ \settrue\c_page_set_defining
+ \dorecurse{\columnsetparameter\c!nleft}
+ {\normalexpanded{\definecolumnset[\currentcolumnset:\recurselevel][\currentcolumnset]}}%
+ \dorecurse{\columnsetparameter\c!nright}
+ {\normalexpanded{\definecolumnset[\currentcolumnset:\recurselevel][\currentcolumnset]}}%
+ \normalexpanded{\page_set_setup_saved[\currentcolumnset:1][\c!distance=\zeropoint]}%
+ \setfalse\c_page_set_defining
+ \fi
+\to \everydefinecolumnset
\unexpanded\def\setupcolumnset
- {\dotripleargument\dosetupcolumnset}
+ {\dotripleargument\page_set_setup}
-\def\dosetupcolumnset[#1][#2][#3]%
+\def\page_set_setup[#1][#2][#3]%
{\ifthirdargument
- \def\docommand##1%
+ \unexpanded\def\page_set_setup_step##1%
{\doifelse{##1}\v!each
- {\dorecurse{\getvalue{\??mc#1\c!n}}{\docommand\recurselevel}}
- {\getparameters[\??mc#1##1][#3]}}%
- \processcommalist[#2]\docommand
+ {\dorecurse{\namedcolumnsetparameter{#1}\c!n}{\page_set_setup_step\recurselevel}}
+ {\normalexpanded{\page_set_setup_saved[#1:\recurselevel]}[#3]}}%
+ \processcommalist[#2]\page_set_setup_step
\else
- \getparameters[\??mc#1][#2]%
+ \page_set_setup_saved[#1][#2]%
\fi}
-
-\definecolumnset[\s!default][\c!n=2] % fallback
-
+
+\definecolumnset
+ [\s!default]
+
\unexpanded\def\page_set_command_next_page
{\page_otr_fill_and_eject_page
\relax\ifnum\mofcolumns>\plusone
@@ -1470,7 +1507,6 @@
\let\page_set_command_next_page_and_inserts\page_set_command_next_page
-
\def\OTRSETgotocolumn
{\dosingleempty\doOTRSETgotocolumn}
@@ -1500,7 +1536,7 @@
\currenthcell\mofcolumns
\currentvcell#1\advance\currentvcell \minusone
\dorecurse\currentvcell
- {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing
+ {\page_set_cell_doifelse\mofcolumns\recurselevel\donothing
{\advance\scratchcounter\plusone}}
\getnoflines\pagetotal
\advance\scratchcounter-\noflines
@@ -1547,7 +1583,7 @@
% \currenthcell\mofcolumns
% \currentvcell#2\advance\currentvcell \minusone
% \dorecurse\currentvcell
-% {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing
+% {\page_set_cell_doifelse\mofcolumns\recurselevel\donothing
% {\advance\scratchcounter\plusone}}
% \getnoflines\pagetotal
% \advance\scratchcounter-\noflines
@@ -1610,7 +1646,7 @@
% \stoptext
\def\OTRSETflushleftovers % new per 13/4/2006
- {\OTRSETdoifcellelse{1}{1}
+ {\page_set_cell_doifelse\plusone\plusone
{\bgroup
\OTRSETcentergridcells
\OTRSETbalancemethod\plusone
@@ -1643,7 +1679,7 @@
\fi
\fi
\global\setfalse\OTRSETfinish
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\page_otr_command_set_vsize
\pagebreak
\page_otr_command_set_vsize
@@ -1725,8 +1761,8 @@
{\doifsomething\OTRSETlist
{\getfromcommacommand[\OTRSETlist][1]%
\global\let\OTRSETidentifier\commalistelement
- \doifundefined{\??mc\OTRSETidentifier\c!n}
- {\globallet\OTRSETidentifier\s!default}%
+ \xdef\currentcolumnset{\commalistelement}%
+ \checkcolumnsetparent
\let\newcommalistelement\empty
\doglobal\replaceincommalist\OTRSETlist1%
\OTRSETrestart}}
@@ -1752,8 +1788,8 @@
\OTRSETsetcorrectnofcells\currentcolumnstartcell
\advance\scratchcounter \minusone
\dorecurse\scratchcounter
- {\OTRSETdoifcellelse\mofcolumns\recurselevel
- \donothing{\OTRSETsetgridcell\mofcolumns\recurselevel\copy\placeholderboxe}}%
+ {\page_set_cell_doifelse\mofcolumns\recurselevel
+ \donothing{\page_set_cell_set\mofcolumns\recurselevel\copy\placeholderboxe}}%
\egroup}}
\unexpanded\def\page_set_command_routine
@@ -1778,13 +1814,13 @@
% new: raw
\OTRSETsetcolumnmaxcells
% direction
- \doifelsevalue{\??mc\OTRSETidentifier\c!direction}\v!right
+ \doifelse{\columnsetparameter\c!direction}\v!right
{\columndirection\zerocount}
{\columndirection\plusone}%
% balancing
\OTRSETbalancemethod\zerocount
\processaction
- [\getvalue{\??mc\OTRSETidentifier\c!balance}]
+ [\columnsetparameter\c!balance]
[ \v!yes=>\OTRSETbalancemethod\plusone,
\v!top=>\OTRSETbalancemethod\plustwo,
\v!bottom=>\OTRSETbalancemethod\plusthree]}
@@ -1803,46 +1839,46 @@
\ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi
\installoutputroutine\OTRSETflushpreposttext
- {\global\setbox\precolumnbox\vbox
+ {\global\setbox\b_page_set_preceding\vbox
{\unvbox\normalpagebox
\global\lastskipinotr\lastskip}%
\ifdim\lastskipinotr>\zeropoint
- \global\setbox\precolumnbox\hbox
- {\lower\strutdepth\box\precolumnbox}%
+ \global\setbox\b_page_set_preceding\hbox
+ {\lower\strutdepth\box\b_page_set_preceding}%
\fi
- \dp\precolumnbox\strutdepth
+ \dp\b_page_set_preceding\strutdepth
\ifcarryoverfootnotes \else
- \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
+ \global\setbox\b_page_set_trailing\vbox{\placebottomnotes}%
\fi}
\let\precolumnlines \!!zerocount
\let\postcolumnlines\!!zerocount
\def\OTRSEThandlepreposttext
- {\ifdim\ht\precolumnbox>\zeropoint % new
- \getnoflines{\ht\precolumnbox}%
+ {\ifdim\ht\b_page_set_preceding>\zeropoint % new
+ \getnoflines{\ht\b_page_set_preceding}%
\edef\precolumnlines{\the\noflines}%
\doOTRSETsetgridcells
{\copy\placeholderboxe}
\plusone\plusone\nofcolumns\noflines
% normal version (single column set)
- % {\box\precolumnbox}%
+ % {\box\b_page_set_preceding}%
% compensated for bodyfont change
{\hbox
{\OTRSETsetcorrectcellht
- \raise\scratchdimen\box\precolumnbox}}%
+ \raise\scratchdimen\box\b_page_set_preceding}}%
\else
\let\precolumnlines\!!zerocount
\fi
- \ifdim\ht\postcolumnbox>\zeropoint % new, otherwise empty bottom line
- \getnoflines{\ht\postcolumnbox}%
+ \ifdim\ht\b_page_set_trailing>\zeropoint % new, otherwise empty bottom line
+ \getnoflines{\ht\b_page_set_trailing}%
\edef\postcolumnlines{\the\noflines}%
\advance\columnfreecells -\noflines
\advance\columnfreecells \plusone
\doOTRSETsetgridcells
{\copy\placeholderboxe}
\plusone\columnfreecells\nofcolumns\noflines
- {\box\postcolumnbox}%
+ {\box\b_page_set_trailing}%
\else
\let\postcolumnlines\!!zerocount
\fi}
@@ -1855,7 +1891,7 @@
\def\OTRSETcheckgrid
{\topskip1\topskip
- \ifforcecolumngrid
+ \ifforcecolumnsetgrid
\widowpenalty\zerocount
\clubpenalty\zerocount
\brokenpenalty\zerocount
@@ -1894,29 +1930,31 @@
% interface to footnotes
+\installcorenamespace{columnsetwidth}
+
\def\OTRSETassignwidths
{%\scratchdimen\makeupwidth
\freezetextwidth \scratchdimen\textwidth
%
\scratchcounter\zerocount
\dorecurse\nofcolumns
- {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!width}\v!fit
- {\advance\scratchcounter \plusone }
- {\advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!width}}%
- \advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!distance}}%
+ {\doifelse{\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}\v!fit
+ {\advance\scratchcounter \plusone}
+ {\advance\scratchdimen -\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}%
+ \advance\scratchdimen -\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
\ifcase\scratchcounter\else
\divide\scratchdimen \scratchcounter
\fi
- \setgvalue{\??mc\??mc\c!width}{0}%
+ \global\setfalse\c_page_set_width_set
\dorecurse\nofcolumns
- {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!width}\v!fit
+ {\doifelse{\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}\v!fit
{\dimen0=\scratchdimen}
- {\setgvalue{\??mc\??mc\c!width}{1}%
- \dimen0=\getvalue{\??mc\OTRSETidentifier\recurselevel\c!width}}%
- \setxvalue{\??mc\recurselevel\??mc\c!width}{\the\dimen0}}}
+ {\global\settrue\c_page_set_width_set
+ \dimen0=\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!width}%
+ \setxvalue{\??columnsetwidth\recurselevel}{\the\dimen0}}}
\def\OTRSETlocalwidth#1%
- {\getvalue{\??mc\number#1\??mc\c!width}}
+ {\getvalue{\??columnsetwidth\number#1}}
\newbox\placeholderboxa
\newbox\placeholderboxb
@@ -1930,7 +1968,7 @@
{\setbox\scratchbox\hbox to \hsize
{\iftracecolumnset
\hskip-.5ex%
- \startcolor[columnset:#2]\vrule\!!width1ex\!!height.5ex\!!depth.5ex\stopcolor
+ \startcolor[columnset:#2]\vrule\s!width\exheight\s!height.5\exheight\s!depth.5\exheight\stopcolor
\fi
\hss}%
\ifcase#1\relax
@@ -1984,14 +2022,14 @@
\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}}
+ {\box\floatbox}
\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
- \doinsertfloatinfo}
+ \page_floats_report_total}
% kind of new, looks much like OTRONE, but not entirely
@@ -1999,7 +2037,7 @@
\unexpanded\def\page_set_command_set_top_insertions
{\bgroup
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\noffloatinserts\zerocount
\let\totaltopinserted\!!zeropoint
\OTRSETdodosettopinserts
@@ -2020,9 +2058,9 @@
\egroup}
\def\OTRSETdodosettopinserts
- {\ifnum\noffloatinserts<\noftopfloats
- \dogetfloat
- \ifdim\topinserted=\zeropoint\relax
+ {\ifnum\noffloatinserts<\c_page_floats_n_of_top
+ \page_floats_get
+ \ifdim\d_page_floats_inserted_top=\zeropoint\relax
\settrue\c_page_set_top_of_insert
\else
\setfalse\c_page_set_top_of_insert
@@ -2038,25 +2076,28 @@
\fi
\page_otr_command_flush_float_box
\blank[\rootfloatparameter\c!spaceafter]}%
- \global\advance\topinserted \ht\scratchbox\relax
- \ifdim\topinserted>\vsize % was \textheight\relax
+ \global\advance\d_page_floats_inserted_top \ht\scratchbox\relax
+ \ifdim\d_page_floats_inserted_top>\vsize % was \textheight\relax
\OTRSETresavebox\floatbox
- \noffloatinserts\noftopfloats\relax
- \global\advance\topinserted -\ht\scratchbox
+ \noffloatinserts\c_page_floats_n_of_top\relax
+ \global\advance\d_page_floats_inserted_top -\ht\scratchbox
\let\OTRSETdodosettopinserts\relax % to be tested
\else
- \xdef\totaltopinserted{\the\topinserted}%
- \insert\topins{\forgetall\box\scratchbox}% interlineskip ?
- \ifsomefloatwaiting
+ \xdef\totaltopinserted{\the\d_page_floats_inserted_top}%
+ \insert\namedinsertionnumber\s!topfloat\bgroup
+ \forgetall
+ \box\scratchbox
+ \egroup
+ \ifconditional\c_page_floats_some_waiting
\advance\noffloatinserts \plusone
\else
- \noffloatinserts\noftopfloats\relax
+ \noffloatinserts\c_page_floats_n_of_top\relax
\fi
- \dofloatflushedinfo
+ \page_floats_report_flushed
\fi
\else
- \ifsomefloatwaiting
- \showmessage\m!floatblocks6{\the\noftopfloats}%
+ \ifconditional\c_page_floats_some_waiting
+ \showmessage\m!floatblocks6{\the\c_page_floats_n_of_top}%
\fi
\let\OTRSETdodosettopinserts\relax
\fi
@@ -2064,67 +2105,66 @@
\unexpanded\def\page_set_command_set_bottom_insertions
{\bgroup
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\noffloatinserts\zerocount
\OTRSETdodosetbotinserts
\fi
\egroup}
\def\OTRSETdodosetbotinserts
- {\ifnum\noffloatinserts<\nofbotfloats\relax
- \dogetfloat
- \global\advance\botinserted \ht\floatbox\relax
- \global\advance\botinserted \dp\floatbox\relax
- \global\advance\botinserted \floattopskip\relax
- \ifdim\botinserted<\pagegoal\relax
- \insert\botins
- {\forgetall
- \blank[\rootfloatparameter\c!spacebefore]%
- \page_otr_command_flush_float_box}%
- \ifsomefloatwaiting
+ {\ifnum\noffloatinserts<\c_page_floats_n_of_bottom\relax
+ \page_floats_get
+ \global\advance\d_page_floats_inserted_bottom\dimexpr\ht\floatbox+\dp\floatbox+\d_strc_floats_top\relax
+ \ifdim\d_page_floats_inserted_bottom<\pagegoal\relax
+ \insert\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup
+ \ifconditional\c_page_floats_some_waiting
\advance\noffloatinserts \plusone
\else
- \noffloatinserts\nofbotfloats
+ \noffloatinserts\c_page_floats_n_of_bottom
\fi
- \dofloatflushedinfo
+ \page_floats_report_flushed
\else
\OTRSETresavebox\floatbox
- \noffloatinserts\nofbotfloats\relax
+ \noffloatinserts\c_page_floats_n_of_bottom\relax
\fi
- \global\nofloatpermittedtrue % vgl topfloats s!
+ \global\settrue\c_page_floats_not_permitted % vgl topfloats s!
\else
- \ifsomefloatwaiting
- \showmessage\m!floatblocks7{\the\nofbotfloats}%
+ \ifconditional\c_page_floats_some_waiting
+ \showmessage\m!floatblocks7{\the\c_page_floats_n_of_bottom}%
\fi
\let\OTRSETdodosetbotinserts\relax
\fi
\OTRSETdodosetbotinserts}
\unexpanded\def\page_set_command_flush_top_insertions
- {\ifvoid\topins\else
+ {\ifvoid\namedinsertionnumber\s!topfloat\else
\ifvoid\columntopbox\mofcolumns
- \columnsettopbox\mofcolumns\box\topins
+ \columnsettopbox\mofcolumns\box\namedinsertionnumber\s!topfloat
\else
\columnsettopbox\mofcolumns\vbox % temp, must be better
{\forgetall
\offinterlineskip
\box\columntopbox\mofcolumns
- \box\topins}
+ \box\namedinsertionnumber\s!topfloat}
\fi
\fi
- \global\topinserted\zeropoint\relax} % goes away
+ \global\d_page_floats_inserted_top\zeropoint\relax} % goes away
\unexpanded\def\page_set_command_flush_bottom_insertions
- {\ifvoid\botins \else
- \columnsetbotbox\mofcolumns\box\botins
+ {\ifvoid\namedinsertionnumber\s!bottomfloat \else
+ \columnsetbotbox\mofcolumns\box\namedinsertionnumber\s!bottomfloat
% \else
% \columnsetbotbox\mofcolumns\vbox % temp, must be better
% {\forgetall
% \offinterlineskip
-% \box\botins
+% \box\namedinsertionnumber\s!bottomfloat
% \box\columnbotbox\mofcolumns}
\fi
- \global\botinserted\zeropoint\relax} % goes away
+ \global\d_page_floats_inserted_bottom\zeropoint\relax} % goes away
% set ipv text
@@ -2135,6 +2175,8 @@
% links rechts => odd, even, n, named
+\definesystemvariable {mt} % MulTicolumn
+
\unexpanded\def\definecolumntextarea
{\dotripleempty\dodefinecolumntextarea}
@@ -2311,7 +2353,7 @@
\c!height=\!!heighta]%
{\copy\scratchbox}%
\fi}%
- \OTRSETsetgridcell\!!counta\!!countb\box0
+ \page_set_cell_set\!!counta\!!countb\box0
\ifcase\!!countc\else
\advance\!!counta \columntextareaparameter\c!nx
\advance\!!counta -\!!countc
@@ -2328,7 +2370,7 @@
\c!height=\!!heighta,%
\c!hoffset=\!!widthb]%
{\copy\scratchbox}}%
- \OTRSETsetgridcell\!!counta\!!countb\box0%
+ \page_set_cell_set\!!counta\!!countb\box0%
\fi}
\unexpanded\def\setupcolumntextareatext
@@ -2366,7 +2408,7 @@
\fi
\advance\!!counta \plusone
\dostepwiserecurse\!!counta\!!countb\plusone
- {\advance\!!widtha\OTRSETgetparameter\c!distance\recurselevel}%
+ {\advance\!!widtha\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
\!!widthb\!!widtha
\advance\!!widthb -\!!countc\textwidth
\ifodd\realpageno \else % tricky, assumes that we keep there
@@ -2376,7 +2418,7 @@
\advance\!!widtha \namedlayoutparameter\v!odd \c!backspace
\advance\!!widthb \namedlayoutparameter\v!even\c!backspace
\dorecurse\!!countc
- {\advance\!!widtha\OTRSETgetparameter\c!distance\recurselevel}%
+ {\advance\!!widtha\namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
\fi
\fi}
@@ -2386,12 +2428,12 @@
{\!!counta#1\!!countb#2\docalculatecolumnsetspan
\edef\columnsetspanhsize{\the\!!widtha}}
-\unexpanded\def\page_set_command_set_float_hsize
+\unexpanded\def\page_set_command_set_float_hsize % this helper has to be moved to strc-flt
{\hsize % maybe checking optional
- \ifdim\tempfloatwidth>\makeupwidth
+ \ifdim\d_strc_float_temp_width>\makeupwidth
\makeupwidth
\else
- \tempfloatwidth
+ \d_strc_float_temp_width
\fi}
\unexpanded\def\definecolumnsetspan
@@ -2538,12 +2580,12 @@
% \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
+ {\global\d_page_floats_inserted_top\zeropoint
+ \global\d_page_floats_inserted_bottom\zeropoint
+ \ifconditional\c_page_floats_flushing \else
\page_set_command_set_top_insertions
\page_set_command_set_bottom_insertions
- \ifsomefloatwaiting
+ \ifconditional\c_page_floats_some_waiting
\doif{\rootfloatparameter\c!cache}\v!no\page_set_command_flush_floats % could be _otr_
\fi
\fi}
diff --git a/tex/context/base/page-sid.mkiv b/tex/context/base/page-sid.mkiv
index f4d42a41c..f7a2357bf 100644
--- a/tex/context/base/page-sid.mkiv
+++ b/tex/context/base/page-sid.mkiv
@@ -68,29 +68,8 @@
\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
-%
-% 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
+\setnewconstant \c_page_sides_align \zerocount
\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}
@@ -104,13 +83,12 @@
\let\logsidefloat \relax
-\newif\ifroomforfloat % shared (will change)
\newif\iftracesidefloats % public (might change)
% end of public variables
\def\page_sides_insert_info
- {\doinsertfloatinfo}
+ {\page_floats_report_total}
\def\page_sides_apply_horizontal_shift
{\ifdim\d_page_sides_maximum>\zeropoint
@@ -211,8 +189,8 @@
+\compensatedinnermakeupmargin
\relax
\fi
- \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}
+ \ifdim\d_page_sides_rightskip>\zeropoint \global\advance\d_page_sides_rightskip\rightskip \fi
+ \ifdim\d_page_sides_leftskip >\zeropoint \global\advance\d_page_sides_leftskip \leftskip \fi}
\def\page_sides_flush_floats
{\par
@@ -232,10 +210,7 @@
\doloop
{\strut
\iftracesidefloats
- \color[darkgray]%
- {\baselinerulefalse
- \boxrulewidth.5\points
- \ruledhbox{\strut\kern\d_page_sides_width}}%
+ \color[darkgray]{\ruledhbox{\strut\kern\d_page_sides_width}}%
\fi
\par
\ifdim\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint
@@ -330,7 +305,9 @@
\ifdim\wd\b_page_sides_bottom<\d_page_sides_hsize
\parskip\zeropoint
%\noindent
- \ifinner\else\vadjust{\penalty\minusone}\fi
+ \ifinner\else
+ \vadjust{\penalty\minusone}%
+ \fi
\ifconditional\c_page_sides_l_eq
\global\setfalse\c_page_sides_l_eq
\else
@@ -421,7 +398,7 @@
\else
\kern\d_page_sides_shift
\fi
- \vbox{#1\ifnum\c_page_sides_align=\plusfour \removedepth\fi}%
+ \vbox{#1\ifnum\c_page_sides_align=\plusfour \removedepth \fi}%
\ifnum\c_page_sides_float_type>\plusfour
\kern\d_page_sides_shift
\else
@@ -535,7 +512,7 @@
\def\page_sides_push_float_inline#1%
{\begingroup
- \everypar\emptytoks % needed !
+ \reseteverypar % needed !
\parskip\zeropoint % needed !
\page_sides_set_skips
\page_sides_insert_info
@@ -579,7 +556,7 @@
\else\ifnum\c_page_sides_float_type>\plusfive
\global\d_page_sides_width\zeropoint
\else
- \global\d_page_sides_width\dimexpr\wd\floatbox+\floatsideskip\relax
+ \global\d_page_sides_width\dimexpr\wd\floatbox+\d_strc_floats_margin\relax
\fi\fi
\ifdim\d_page_sides_width<\zeropoint
\global\d_page_sides_width\zeropoint
@@ -601,7 +578,7 @@
\fi
\relax % really needed ! ! ! !
\ifdim\dimen0>\dimen2
- \global\roomforfloatfalse
+ \global\setfalse\c_page_floats_room
\else
\ifdim\dimexpr\pagegoal-\d_page_sides_vsize\relax<\d_page_sides_bottomskip
\global\advance\d_page_sides_vsize \dimen0
@@ -612,15 +589,15 @@
\global\advance\d_page_sides_vsize \d_page_sides_bottomskip
\global\setfalse\c_page_sides_short
\fi
- \global\roomforfloattrue
+ \global\settrue\c_page_floats_room
\fi}
\def\page_sides_prepare_space
{\par
\whitespace
\begingroup
- \everypar\emptytoks
\forgetall
+ \reseteverypar
\verticalstrut
\vskip-\struttotal
\endgroup}
@@ -633,7 +610,7 @@
\page_sides_relocate_float{#1}%
\page_sides_apply_vertical_shift
\page_sides_analyse_space
- \ifroomforfloat \else
+ \ifconditional\c_page_floats_room \else
\page_otr_fill_and_eject_page
\page_sides_analyse_space
\page_sides_inject_dummy_lines
@@ -653,9 +630,6 @@
\let\page_sides_check_floats\page_sides_check_floats_indeed
-\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
@@ -704,7 +678,7 @@
\iftracesidefloats
\hskip-\d_page_sides_width % kern
\color[darkgray]%
- {\vrule\!!height.5\points\!!depth.5\points\!!width\d_page_sides_width
+ {\vrule\s!height.5\points\s!depth.5\points\s!width\d_page_sides_width
\llap{\showstruts\strut\kern.25\bodyfontsize}}%
\fi}
@@ -788,7 +762,7 @@
% some will become obsolete
\def\checksidefloat {\page_sides_check_floats}
-%def\flushsidefloats {\page_sides_flush_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}
diff --git a/tex/context/base/page-spr.mkiv b/tex/context/base/page-spr.mkiv
index f4768d4e9..dc1e013d5 100644
--- a/tex/context/base/page-spr.mkiv
+++ b/tex/context/base/page-spr.mkiv
@@ -17,10 +17,9 @@
\unprotect
-\newbox\spreadbox
-\newif \ifinspread
-
-\setnewconstant\showspreadmode\plusone
+\newbox \b_page_spread_content
+\newconditional\c_page_spread_busy
+\newconditional\c_page_spread_once % when true only one flush (writes etc)
% beware, ugly overload, to be redone
@@ -35,52 +34,81 @@
\noindent % content can be < \hsize
\page_otr_command_package_contents#2#3}}%
\dp#1\zeropoint
- \setbox#1\hbox to \makeupwidth
- {\ifinspread
- \ifvoid\spreadbox
- \global\setbox\spreadbox\box#1%
- \copy\spreadbox\hss % left page
+ \ifconditional\c_page_spread_busy
+ \normalsettextpagecontent_spread{#1}%
+ \else
+ \normalsettextpagecontent_normal{#1}%
+ \fi}
+
+\def\normalsettextpagecontent_normal#1%
+ {\setbox#1\hbox to \makeupwidth
+ {\hss\box#1\hss}} % never change the \hss's
+
+\def\normalsettextpagecontent_spread#1%
+ {\setbox#1\hbox to \makeupwidth
+ {\ifvoid\b_page_spread_content
+ \ifconditional\c_page_spread_once
+ \box#1%
\else
- % prevent duplicate writes in normal run
- \ifarrangingpages \else \ifcase\showspreadmode
- \global\setbox\spreadbox\emptyhbox
- \wd\spreadbox\makeupwidth
- \ht\spreadbox\textheight
- \fi \fi
- \hss\box\spreadbox % right page
+ \global\setbox\b_page_spread_content\box#1%
+ \copy\b_page_spread_content
\fi
+ \hss % left page
\else
- \hss\box#1\hss % never change the \hss's
+ \hss % right page
+ \ifarrangingpages
+ % writes don't matter anyway
+ \else\ifconditional\c_page_spread_once
+ \global\setbox\b_page_spread_content\emptyhbox
+ \wd\b_page_spread_content\makeupwidth
+ \ht\b_page_spread_content\textheight
+ \else
+ % writes can interfere (todo: write stripper, but how about hyperlinks)
+ \fi \fi
+ \box\b_page_spread_content
\fi}}
-\def\doflushspread
- {\ifinspread \ifvoid\spreadbox\else
+\unexpanded\def\page_spread_flush
+ {\ifconditional\c_page_spread_busy \ifvoid\b_page_spread_content\else
% this page will be discarded later
\emptyhbox \page
\fi \fi }
\unexpanded\def\startspread
- {\bgroup
- \ifdoublesided
- \page[\v!left]%
- %\setsystemmode{spread}%
- \inspreadtrue
- \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}%
- \unexpanded\def\startspread{\bgroup\let\stopspread\egroup}%
- \let\stopspread\dostopspread
+ {\ifdoublesided
+ \ifconditional\c_page_spread_busy
+ \doubleexpandafter\page_spread_start_nop
+ \else
+ \doubleexpandafter\page_spread_start_yes
+ \fi
\else
- \let\stopspread\egroup
+ \expandafter\page_spread_start_nop
\fi}
\let\stopspread\relax
-\def\dostopspread
- {\kern\zeropoint\page
- \inspreadfalse
+\unexpanded\def\page_spread_start_yes
+ {\bgroup
+ \page[\v!left]%
+ %\setsystemmode{spread}%
+ \settrue\c_page_spread_busy
+ \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}%
+ \let\stopspread\page_spread_stop_yes}
+
+\unexpanded\def\page_spread_stop_yes
+ {\kern\zeropoint
+ \page
\setuplayout[\c!textwidth=\textwidth]
\page[\v!left]
\egroup}
+\unexpanded\def\page_spread_start_nop
+ {\bgroup
+ \let\stopspread\page_spread_stop_nop}
+
+\unexpanded\def\page_spread_stop_nop
+ {\egroup}
+
\protect \endinput
% texexec --arr --pdf test
diff --git a/tex/context/base/page-str.mkiv b/tex/context/base/page-str.mkiv
index f14f2f716..200a71377 100644
--- a/tex/context/base/page-str.mkiv
+++ b/tex/context/base/page-str.mkiv
@@ -36,25 +36,25 @@
\unprotect
\let \currentoutputstream \empty
-\newif \ifinoutputstream
+\newif \ifinoutputstream % will becoem a conditional or mode
\newtoks \everyenableoutputstream
\appendtoks
\page_otr_command_flush_side_floats
\to \everyenableoutputstream
-\def\initializeoutputstreams
+\unexpanded\def\initializeoutputstreams
{\ctxlua{streams.initialize()}%
\glet\initializeoutputstreams\relax}
-\def\enableoutputstream[#1]% could be \startoutputsubstream
+\unexpanded\def\enableoutputstream[#1]% could be \startoutputsubstream
{\initializeoutputstreams
\the\everyenableoutputstream
\inoutputstreamtrue
\xdef\currentoutputstream{#1}%
\ctxlua{streams.enable("#1")}}
-\def\disableoutputstream
+\unexpanded\def\disableoutputstream
{\inoutputstreamfalse
\global\let\currentoutputstream\s!default
\ctxlua{streams.disable()}}
@@ -71,15 +71,13 @@
{\ctxlua{streams.stop()}%
\endgroup}
-\let\currentoutputsubstream\empty
-
-\def\startoutputsubstream[#1]%
- {\glet\savedcurrentoutputstream\currentoutputstream
+\unexpanded\def\startoutputsubstream[#1]% just push/pop instead
+ {\globalpushmacro\currentoutputstream
\enableoutputstream[#1]}
-\def\stopoutputsubstream
- {\glet\currentoutputstream\savedcurrentoutputstream
- \enableoutputstream[\savedcurrentoutputstream]}
+\unexpanded\def\stopoutputsubstream
+ {\globalpopmacro\currentoutputstream
+ \enableoutputstream[\currentoutputstream]}
\def\flushoutputstream [#1]{\ctxlua{streams.flush("#1")}}
\def\outputstreamcopy [#1]{\vbox{\ctxlua{streams.flush("#1",true)}}}
@@ -89,7 +87,8 @@
\def\synchronizestreams [#1]{\ctxlua{streams.synchronize("#1")}}
\def\dopushoutputstream [#1]{\ctxlua{streams.push("#1")}}
-\def\pushoutputstream {\dosingleempty\dopushoutputstream}
+\unexpanded\def\pushoutputstream
+ {\dosingleempty\dopushoutputstream}
% \unexpanded\def\defineoutputstream[#1]%
% {\doifundefined{otrs:#1}{\expandafter\newbox\csname otrs:#1\endcsname}}
@@ -103,13 +102,15 @@
% \directsetup{stream:\firstoutputstream:bottom}
% \directsetup{stream:\firstoutputstream:reset}
-%D Obsolete in \MKIV:
-
-\unexpanded\def\definemarknote {\dodoubleempty\dodefinemarknote}
-\def\dodefinemarknote[#1][#2]{}
-\def\setmarknote [#1]{\gobbleoneargument}
-\def\flushmarknotes [#1]{}
-\def\erasemarknotes [#1]{}
+% Obsolete in \MKIV:
+%
+% \unexpanded\def\definemarknote
+% {\dodoubleempty\dodefinemarknote}
+%
+% \def\dodefinemarknote[#1][#2]{}
+% \def\setmarknote [#1]{\gobbleoneargument}
+% \def\flushmarknotes [#1]{}
+% \def\erasemarknotes [#1]{}
\protect \endinput
diff --git a/tex/context/base/page-txt.mkvi b/tex/context/base/page-txt.mkvi
index c86597338..dc445e0e1 100644
--- a/tex/context/base/page-txt.mkvi
+++ b/tex/context/base/page-txt.mkvi
@@ -430,6 +430,9 @@
\global\setfalse\resyncaftertextline
\fi}
+\def\getspecificlayouttext#vertical#horizontal#what%
+ {\csname\namedlayoutelementhash{#vertical:#horizontal}#what\endcsname}
+
% \settext[header][text][middle][xxx][yyy]
\def\settextcontent
@@ -474,8 +477,6 @@
%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
@@ -693,26 +694,26 @@
% 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
+\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_place_page_number % also elsewhere .. beware, not \unexpanded else
+ {\strc_pagenumbers_place_location} % 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}%
+ {\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}%
+ {\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
+ {\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
@@ -721,38 +722,39 @@
\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_
+ {\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[\directpagenumberingparameter\c!location]
+ [ \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\strc_pagenumbers_set_location
+ {\edef\p_strc_pagenumbers_location{\directpagenumberingparameter\c!location}%
+ \ifx\p_strc_pagenumbers_location\m_page_layouts_page_number_location
% unchanged
\else
- \let\m_page_layouts_page_number_location_\@@nmlocation
+ \let\m_page_layouts_page_number_location\p_strc_pagenumbers_location
\page_layouts_reset_page_number_location
- \ifx\@@nmlocation\empty
+ \ifx\p_strc_pagenumbers_location\empty
% set otherwise
\else
\page_layouts_identify_page_number_location
@@ -764,9 +766,12 @@
{\begingroup
\setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
\ifzeropt\wd\scratchbox\else
- \doifelsenothing\@@nmwidth
- {\box\scratchbox\tfskip}
- {\hbox to \@@nmwidth{\box\scratchbox\hss}}%
+ \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}%
+ \ifx\p_strc_pagenumbers_width\empty
+ \box\scratchbox\tfskip
+ \else
+ \hbox to \p_strc_pagenumbers_width{\box\scratchbox\hss}%
+ \fi
\fi
\endgroup}
@@ -774,13 +779,16 @@
{\begingroup
\setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
\ifzeropt\wd\scratchbox\else
- \doifelsenothing\@@nmwidth
- {\tfskip\box\scratchbox}
- {\hbox to \@@nmwidth{\hss\box\scratchbox}}%
+ \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}%
+ \ifx\p_strc_pagenumbers_width\empty
+ \tfskip\box\scratchbox
+ \else
+ \hbox to \p_strc_pagenumbers_width{\hss\box\scratchbox}%
+ \fi
\fi
\endgroup}
-\dosetpagenumberlocation
+\strc_pagenumbers_set_location % initializes
% will go to page-box.mkiv
@@ -839,7 +847,7 @@
\kern\dimexpr\leftmarginwidth+\leftmargindistance\relax
\fi
\endgroup
- \mkprocesspagecontents{#2}%
+ \page_postprocessors_page{#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
diff --git a/tex/context/base/phys-dim.lua b/tex/context/base/phys-dim.lua
index c47821b1c..5b883ac88 100644
--- a/tex/context/base/phys-dim.lua
+++ b/tex/context/base/phys-dim.lua
@@ -116,27 +116,51 @@ local dnumber = (ddigitspace + ddigit)^1
-- : ; 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
+-- 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
+--
+-- fix by WS/SB (needs further testing)
+
+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 -- :==
+ dfinalperiod * ddigit * (dintercomma * ddigit)^0 -- .00
+ + dskipperiod * dpadding^1 -- .==
+ + dsemiperiod * ddigit * (dintercomma * ddigit)^0 -- :00
+ + dsemiperiod * dpadding^1 -- :==
)^0
- + ddigit -- 00
+ + ddigit -- 00
-local p_c = (ddigitspace^1 * dskipperiod)^0 -- ___.
- * (ddigitspace^0 * ddigit * dinterperiod)^0 -- _00. 000.
- * ddigitspace^0 * ddigit^0 -- _00 000
+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 -- :==
+ dfinalcomma * ddigit * (dinterperiod * ddigit)^0 -- 00
+ + dskipcomma * dpadding^1 -- ,==
+ + dsemicomma * ddigit * (dinterperiod * ddigit)^0 -- :00
+ + dsemicomma * dpadding^1 -- :==
)^0
- + ddigit -- 00
+ + 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
@@ -482,7 +506,7 @@ local unitsNspace = context.unitsNspace
local labels = languages.data.labels
-labels.prefixes = {
+labels.prefixes = allocate {
yocto = { labels = { en = [[y]] } }, -- 10^{-24}
zepto = { labels = { en = [[z]] } }, -- 10^{-21}
atto = { labels = { en = [[a]] } }, -- 10^{-18}
@@ -515,7 +539,7 @@ labels.prefixes = {
root = { labels = { en = [[√]] } }, -- 0x221A
}
-labels.units = {
+labels.units = allocate {
meter = { labels = { en = [[m]] } },
gram = { labels = { en = [[g]] } }, -- strictly kg is the base unit
second = { labels = { en = [[s]] } },
@@ -597,14 +621,14 @@ labels.units = {
micron = { labels = { en = [[\textmu m]] } },
}
-labels.operators = {
+labels.operators = allocate {
times = { labels = { en = [[\unitsTIMES]] } },
solidus = { labels = { en = [[\unitsSOLIDUS]] } },
per = { labels = { en = [[\unitsSOLIDUS]] } },
outof = { labels = { en = [[\unitsOUTOF]] } },
}
-labels.suffixes = {
+labels.suffixes = allocate {
linear = { labels = { en = [[1]] } },
square = { labels = { en = [[2]] } },
cubic = { labels = { en = [[3]] } },
@@ -849,7 +873,7 @@ local t_shortcuts = {
suffixes = setmetatablenewindex(short_suffixes,trigger),
}
-physics.units.tables = {
+physics.units.tables = allocate {
units = t_units,
shortcuts = t_shortcuts,
}
diff --git a/tex/context/base/phys-dim.mkiv b/tex/context/base/phys-dim.mkiv
index 84c3c7a2a..934985399 100644
--- a/tex/context/base/phys-dim.mkiv
+++ b/tex/context/base/phys-dim.mkiv
@@ -216,10 +216,15 @@
\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\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
+
+\unexpanded\def\digitsfinalcomma {\digitsperiodsymbol} % more for tracing
\unexpanded\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing
\unexpanded\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing
-\unexpanded\def\digitsintermediateperiod {\digitsperiodsymbol} % more for tracing
+\unexpanded\def\digitsintermediateperiod {\digitscommasymbol } % more for tracing
%D The user macro:
@@ -639,12 +644,10 @@
\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")%
-}
+\ctxcommand{definelabels("prefix", "prefixes" )}
+\ctxcommand{definelabels("unit", "units" )}
+\ctxcommand{definelabels("operator","operators")}
+\ctxcommand{definelabels("suffix", "suffixes" )}
%D You can define additional units:
%D
diff --git a/tex/context/base/ppchtex.mkiv b/tex/context/base/ppchtex.mkiv
index a14578ceb..0f42f91ce 100644
--- a/tex/context/base/ppchtex.mkiv
+++ b/tex/context/base/ppchtex.mkiv
@@ -474,9 +474,9 @@
\or
\resetchemicalcoordinates
\setbox2\hbox{\ignoreMPboxdepth\getMPdrawing}%
- \wd2=\!!zeropoint
- \ht2=\!!zeropoint
- \dp2=\!!zeropoint
+ \wd2\zeropoint
+ \ht2\zeropoint
+ \dp2\zeropoint
\put {\box2} at 0 0
\endpicture
\popMPdrawing
@@ -515,9 +515,9 @@
\ifMPdrawingdone
\resetchemicalcoordinates
\setbox2\hbox{\ignoreMPboxdepth\getMPdrawing}%
- \wd2=\!!zeropoint
- \ht2=\!!zeropoint
- \dp2=\!!zeropoint
+ \wd2\zeropoint
+ \ht2\zeropoint
+ \dp2\zeropoint
\put {\box2} at 0 0 %
\fi
\endpicture
@@ -576,7 +576,7 @@
\!!widtha=50.8mm
\divide\!!widtha by \@@chemicalresolution\relax
\plotsymbolspacing=\!!widtha
- \setplotsymbol({\vrule\!!height\!!widtha\!!width\!!widtha})%
+ \setplotsymbol({\vrule\s!height\!!widtha\s!width\!!widtha})%
\fi}
% Something for Dirk:
@@ -2149,8 +2149,8 @@
\ifdim\wd4>\dimen2 \dimen0=\wd4 \fi
\chemicaloutermolecule
{#1}
- {\ifdim\ht2>\!!zeropoint\box2\fi} % expands to \empty in test
- {\ifdim\ht4>\!!zeropoint\box4\fi}% % expands to \empty in test
+ {\ifdim\ht2>\zeropoint\box2\fi} % expands to \empty in test
+ {\ifdim\ht4>\zeropoint\box4\fi}% % expands to \empty in test
\egroup}
\def\chemicalsingleouterarrow
diff --git a/tex/context/base/prop-ini.mkiv b/tex/context/base/prop-ini.mkiv
index d8d2ea2f4..3b1c59b24 100644
--- a/tex/context/base/prop-ini.mkiv
+++ b/tex/context/base/prop-ini.mkiv
@@ -37,7 +37,7 @@
\def\properties_define[#1][#2][#3]%
{\properties_obsolete_message
- \setevalue{\??propertytypes#1e}{#2}%
+ \setevalue{\??propertytypes#1}{#2}%
\getvalue{\??propertydefiners#2}[#1][#2][#3]}
\setvalue{\??propertystarters\v!layer }#1{\let\properties_stop\stopviewerlayer\startviewerlayer[#1]}
diff --git a/tex/context/base/regi-ini.lua b/tex/context/base/regi-ini.lua
index ec6f812cc..f9507bd0b 100644
--- a/tex/context/base/regi-ini.lua
+++ b/tex/context/base/regi-ini.lua
@@ -12,11 +12,13 @@ if not modules then modules = { } end modules ['regi-ini'] = {
runtime.</p>
--ldx]]--
-local utfchar, utfgsub = utf.char, utf.gsub
+local commands, context = commands, context
+
+local utfchar = utf.char
+local lpegmatch = lpeg.match
local char, gsub, format = string.char, string.gsub, string.format
local next = next
-local insert, remove = table.insert, table.remove
-
+local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
local allocate = utilities.storage.allocate
local sequencers = utilities.sequencers
@@ -138,17 +140,51 @@ local function translate(line,regime)
return line
end
+-- local remappers = { }
+--
+-- local function toregime(vector,str,default) -- toregime('8859-1',"abcde Ä","?")
+-- local t = backmapping[vector]
+-- local remapper = remappers[vector]
+-- if not remapper then
+-- remapper = utf.remapper(t)
+-- remappers[t] = remapper
+-- end
+-- local m = getmetatable(t)
+-- setmetatableindex(t, function(t,k)
+-- local v = default or "?"
+-- t[k] = v
+-- return v
+-- end)
+-- str = remapper(str)
+-- setmetatable(t,m)
+-- return str
+-- end
+--
+-- -- much faster (but only matters when we have > 10K calls
+
+local cache = { } -- if really needed we can copy vectors and hash defaults
+
+setmetatableindex(cache, function(t,k)
+ local v = { remappers = { } }
+ t[k] = v
+ return v
+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
+ local d = default or "?"
+ local c = cache[vector].remappers
+ local r = c[d]
+ if not r then
+ local t = fastcopy(backmapping[vector])
+ setmetatableindex(t, function(t,k)
+ local v = d
+ t[k] = v
+ return v
+ end)
+ r = utf.remapper(t)
+ c[d] = r
+ end
+ return r(str)
end
local function disable()
@@ -186,14 +222,14 @@ function regimes.process(str,filename,currentline,noflines,coding)
return str
end
-function regimes.push()
+local function push()
level = level + 1
if trace_translating then
report_translating("pushing level: %s",level)
end
end
-function regimes.pop()
+local function pop()
if level > 0 then
if trace_translating then
report_translating("popping level: %s",level)
@@ -202,6 +238,9 @@ function regimes.pop()
end
end
+regimes.push = push
+regimes.pop = pop
+
sequencers.prependaction(textlineactions,"system","regimes.process")
sequencers.disableaction(textlineactions,"regimes.process")
@@ -210,6 +249,9 @@ sequencers.disableaction(textlineactions,"regimes.process")
commands.enableregime = enable
commands.disableregime = disable
+commands.pushregime = push
+commands.popregime = pop
+
function commands.currentregime()
context(currentregime)
end
diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex
index d6685bd71..87fb72863 100644
--- a/tex/context/base/s-abr-01.tex
+++ b/tex/context/base/s-abr-01.tex
@@ -19,279 +19,291 @@
\protect
-\logo [MKI] {MkI} % joke
-\logo [MKII] {MkII}
-\logo [MKIII] {MkIII} % joke
-\logo [MKIV] {MkIV}
-\logo [MKVI] {MkVI}
-\logo [MPII] {MpII}
-\logo [MPIV] {MpIV}
+\logo [MKI] {MkI} % joke
+\logo [MKII] {MkII}
+\logo [MKIII] {MkIII} % joke
+\logo [MKIV] {MkIV}
+\logo [MKVI] {MkVI}
+\logo [MKIX] {MkIX}
+\logo [MKXI] {MkXI}
+\logo [MKIC] {MkIC}
+\logo [MKCI] {MkCI}
+\logo [MPII] {MpII}
+\logo [MPIV] {MpIV}
-%logo [FGA] {fga}
-%logo [FGBBS] {fgbbs}
-\logo [ACROBAT] {Acro\-bat}
-\logo [AFM] {afm}
-\logo [API] {api}
-\logo [ALEPH] {Aleph} % {\mathematics{\aleph}}
-\logo [ALGOL] {ALGOL}
-\logo [AMS] {ams}
-\logo [AMSLATEX] {\AmSLaTeX}
-\logo [AMSTEX] {\AmSTeX}
-\logo [ANSI] {ansi}
-\logo [ARABTEX] {Arab\TeX}
-\logo [ASCII] {ascii}
-\logo [ASCIITEX] {ascii\TeX}
-\logo [BACHOTEX] {Bacho\TeX}
-\logo [BIBTEX] {bib\TeX}
-\logo [BLUESKY] {BlueSky}
-\logo [BMP] {bmp}
-\logo [BSD] {bsd}
-\logo [CCODE] {C}
-\logo [CPLUSPLUS] {C\high{++}}
-\logo [CALCMATH] {CalcMath}
-\logo [CD] {cd}
-\logo [CPU] {cpu}
-\logo [CDROM] {cdrom}
-\logo [CID] {cid}
-\logo [CJK] {cjk}
-\logo [CMR] {cmr}
-\logo [CLD] {cld}
-\logo [CMYK] {cmyk}
-\logo [CODHOST] {CodHost}
-\logo [CONTEXT] {\ConTeXt}
-\logo [CSS] {css}
-\logo [CTAN] {ctan}
-\logo [CTXTOOLS] {ctxtools}
-\logo [CWEB] {cweb}
-\logo [DANTE] {Dante}
-\logo [DISTILLER] {distiller}
-\logo [DRATEX] {Dra\TeX}
-\logo [DSC] {dsc}
-\logo [DTD] {dtd}
-\logo [DTK] {dtk}
-\logo [DTP] {dtp}
-\logo [DVD] {dvd}
-\logo [DVI] {dvi}
-\logo [DVIPDFM] {dvipdfm}
-\logo [DVIPDFMX] {dvipdfmx}
-\logo [DVIPOS] {dvipos}
-\logo [DVIPS] {dvips}
-\logo [DVIPSONE] {dvipsone}
-\logo [DVISCR] {dviscr}
-\logo [DVIWINDO] {dviwindo}
-\logo [EBCDIC] {ebcdic}
-\logo [EC] {ec}
-\logo [EIFFEL] {Eiffel}
-\logo [EMACS] {emacs}
-\logo [EMTEX] {em\TeX}
-\logo [ENCODING] {enc}
-\logo [ENCTEX] {enc\TeX}
-\logo [EPS] {eps}
-\logo [ETEX] {\eTeX}
+%logo [FGA] {fga}
+%logo [FGBBS] {fgbbs}
+\logo [ACROBAT] {Acro\-bat}
+\logo [AFM] {afm}
+\logo [API] {api}
+\logo [ALEPH] {Aleph} % {\mathematics{\aleph}}
+\logo [ALGOL] {ALGOL}
+\logo [AMS] {ams}
+\logo [AMSLATEX] {\AmSLaTeX}
+\logo [AMSTEX] {\AmSTeX}
+\logo [ANSI] {ansi}
+\logo [ARABTEX] {Arab\TeX}
+\logo [ASCII] {ascii}
+\logo [ASCIITEX] {ascii\TeX}
+\logo [BACHOTEX] {Bacho\TeX}
+\logo [BIBTEX] {bib\TeX}
+\logo [BLUESKY] {BlueSky}
+\logo [BMP] {bmp}
+\logo [BSD] {bsd}
+\logo [CCODE] {C}
+\logo [CPLUSPLUS] {C\high{++}}
+\logo [CALCMATH] {CalcMath}
+\logo [CD] {cd}
+\logo [CPU] {cpu}
+\logo [CDROM] {cdrom}
+\logo [CID] {cid}
+\logo [CJK] {cjk}
+\logo [CMR] {cmr}
+\logo [CLD] {cld}
+\logo [CMYK] {cmyk}
+\logo [CODHOST] {CodHost}
+\logo [CONTEXT] {\ConTeXt}
+\logo [CSS] {css}
+\logo [CTAN] {ctan}
+\logo [CTXTOOLS] {ctxtools}
+\logo [CWEB] {cweb}
+\logo [CSTUG] {cstug}
+\logo [DANTE] {Dante}
+\logo [DISTILLER] {distiller}
+\logo [DRATEX] {Dra\TeX}
+\logo [DSC] {dsc}
+\logo [DTD] {dtd}
+\logo [DTK] {dtk}
+\logo [DTP] {dtp}
+\logo [DVD] {dvd}
+\logo [DVI] {dvi}
+\logo [DVIPDFM] {dvipdfm}
+\logo [DVIPDFMX] {dvipdfmx}
+\logo [DVIPOS] {dvipos}
+\logo [DVIPS] {dvips}
+\logo [DVIPSONE] {dvipsone}
+\logo [DVISCR] {dviscr}
+\logo [DVIWINDO] {dviwindo}
+\logo [EBCDIC] {ebcdic}
+\logo [EC] {ec}
+\logo [EIFFEL] {Eiffel}
+\logo [EMACS] {emacs}
+\logo [EMTEX] {em\TeX}
+\logo [ENCODING] {enc}
+\logo [ENCTEX] {enc\TeX}
+\logo [EPS] {eps}
+\logo [ETEX] {\eTeX}
\logo [EUROBACHOTEX] {EuroBacho\TeX}
-\logo [EUROMATH] {EuroMath}
-\logo [EUROTEX] {Euro\TeX}
-\logo [EXAMPLE] {eXaMpLe}
-\logo [EXAMPLED] {exampled}
-\logo [EXAMPLEQ] {exampleq}
-\logo [EXAMPLER] {exampler}
-\logo [EXAMPLET] {examplet}
-\logo [EXAMPLEX] {examplex}
-\logo [EXIMPLE] {eXiMpLe}
-\logo [FLAC] {flac}
-\logo [FAQ] {faq}
-\logo [FDF] {fdf}
-\logo [FONTFORGE] {FontForge}
-\logo [FOXET] {foXet}
-\logo [FPTEX] {fp\TeX}
-\logo [FREEBSD] {FreeBSD}
-\logo [FTP] {ftp}
-\logo [GHOSTSCRIPT]{Ghost\-script}
-\logo [GHOSTVIEW] {Ghost\-view}
-\logo [GIF] {gif}
-\logo [GNU] {gnu}
-\logo [GNUPLOT] {gnuplot}
-\logo [GS] {Ghost\-Script}
-\logo [GUST] {Gust}
-\logo [GWTEX] {gw\TeX}
-\logo [HSB] {hsb}
-\logo [HTML] {html}
-\logo [HTTP] {http}
-\logo [HZ] {hz}
-\logo [IBM] {ibm}
-\logo [IMAGEMAGICK]{ImageMagick}
-\logo [INITEX] {ini\TeX}
-\logo [INRSTEX] {inrs\TeX}
-\logo [IO] {io}
-\logo [IRCNET] {IRCnet}
-\logo [ISO] {iso}
-\logo [JAVA] {Java}
-\logo [JAVASCRIPT] {Java\-Script}
-\logo [JPEG] {jpeg}
-\logo [JPG] {jpg}
-\logo [KPATHSEA] {kpathsea}
-\logo [KPSE] {kpse}
-\logo [KPSEWHICH] {kpsewhich}
-\logo [MKTEXLSR] {mktexlsr}
-\logo [LAMSTEX] {\LamSTeX}
-\logo [LATEX] {\LaTeX}
-\logo [LATEXTE] {\LaTeX2e}
-\logo [LATEXTN] {\LaTeX2.09}
-\logo [LCD] {lcd}
-\logo [LINUX] {linux}
-\logo [LISP] {Lisp}
-\logo [LPEG] {lpeg}
-\logo [LUA] {Lua}
-\logo [LUAJIT] {LuaJIT}
-\logo [LUATEX] {Lua\TeX}
-\logo [LUATOOLS] {luatools}
-\logo [MACOSX] {MacOSX}
-\logo [MACROTEX] {Macro\TeX}
-\logo [MAKEMPY] {MakeMPY}
-\logo [MAPPING] {map}
-\logo [MAPS] {Maps}
-\logo [MATHML] {MathML}
-\logo [METAFONT] {\MetaFont}
-\logo [METAPOST] {\MetaPost}
-\logo [METATEX] {Meta\TeX}
-\logo [MIKTEX] {Mik\TeX}
-\logo [MLTEX] {ml\TeX}
-\logo [METATYPE] {MetaType1}
-\logo [MODULA] {Modula}
-\logo [MOV] {mov}
-\logo [MPS] {mps}
-\logo [MPTOPDF] {mptopdf}
-\logo [MPLIB] {mplib}
-\logo [MSDOS] {msdos}
-\logo [MICROSOFT] {Microsoft}
-\logo [MSWINDOWS] {MS~Windows}
-\logo [MTXRUN] {mtxrun}
-\logo [MTXTOOLS] {mtxtools}
-\logo [NETPBM] {NetPBM}
-\logo [NTG] {ntg}
-\logo [NTS] {nts}
-\logo [OFM] {ofm}
-\logo [OMEGA] {Omega}
-\logo [OPENMATH] {OpenMath}
-\logo [OPENTYPE] {OpenType}
-\logo [OPI] {opi}
-\logo [OTF] {otf}
-\logo [OTP] {otp}
-\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}
-\logo [PDFTOOLS] {pdftools}
-\logo [PDFTOPS] {pdftops}
-\logo [PERL] {Perl}
-\logo [PERLTK] {Perl/Tk}
-\logo [PICTEX] {\PiCTeX}
-\logo [PK] {pk}
-\logo [PLAIN] {Plain}
-\logo [PNG] {png}
-\logo [POSIX] {posix}
-\logo [POSTSCRIPT] {Post\-Script}
-\logo [PPCHTEX] {\PPCHTeX}
-\logo [PRAGMA] {Pragma ADE}
-\logo [PRESS] {press}
-\logo [PRIFIL] {prifil}
-\logo [PS] {Post\-Script}
-\logo [PSCHECK] {pscheck}
-\logo [PSTOEDIT] {pstoedit}
-\logo [PSTOPAGE] {pstopage}
-\logo [PSTOPDF] {pstopdf}
-\logo [PSTRICKS] {pstricks}
-\logo [RAM] {ram}
-\logo [READER] {Acro\-bat Reader}
-\logo [RELAXNG] {Relax\kern.125emNG}
-\logo [RGB] {rgb}
-\logo [RLXTOOLS] {rlxtools}
-\logo [RUBY] {Ruby}
-\logo [SCITE] {SciTE}
-\logo [SGML] {sgml}
-\logo [SI] {si}
-\logo [SQL] {sql}
-\logo [SVG] {svg}
-\logo [TABLE] {\TaBlE}
-\logo [TCPIP] {tcp/ip}
-\logo [TDS] {tds} % no sc te
-\logo [TETEX] {te\TeX} % no sc te
-\logo [TEX] {\TeX}
-\logo [TEXADRES] {\TeX adress}
-\logo [TEXBASE] {\TeX base}
-\logo [TEXEDIT] {\TeX edit}
-\logo [TEXEXEC] {\TeX exec}
-\logo [TEXFONT] {\TeX font}
-\logo [TEXFORM] {\TeX form}
-\logo [TEXLIVE] {\TeX Live}
-\logo [TEXLUA] {\TeX Lua}
-\logo [TEXMF] {texmf}
-\logo [TEXMFSTART] {texmfstart}
-\logo [TEXNL] {tex-nl}
-\logo [TEXSHOW] {\TeX show}
-\logo [TEXSPELL] {\TeX spell}
-\logo [TEXGYRE] {\TeX\ Gyre}
-\logo [TEXSYNC] {texsync}
-\logo [TEXTMATE] {TextMate}
-\logo [TEXTOOLS] {\TeX tools}
-\logo [TEXUTIL] {\TeX util}
-\logo [TEXWORK] {\TeX work}
-\logo [TEXXET] {\TeX\XeT} \def\XeT{XeT}
-\logo [TFM] {tfm}
-\logo [TIF] {tif}
-\logo [TIFF] {tiff}
-\logo [TIFFINFO] {tiffinfo}
-\logo [TIFFTAGS] {tifftags}
-\logo [TMFTOOLS] {tmftools}
-\logo [TPIC] {tpic}
-\logo [TPM] {tpm}
-\logo [TRUETYPE] {TrueType}
-\logo [TTC] {ttc}
-\logo [TTF] {ttf}
-\logo [TUG] {tug}
-\logo [TUGBOAT] {Tug\-Boat}
-\logo [TUGNEWS] {Tug\-News}
-\logo [TYPEONE] {Type1}
-\logo [UCS] {ucs}
-\logo [UNICODE] {Uni\-code}
-\logo [UNIX] {Unix}
-\logo [URI] {uri}
-\logo [URL] {url}
-\logo [USA] {usa}
-\logo [USENET] {usenet}
-\logo [UTF] {utf}
-\logo [USB] {usb}
-\logo [VF] {vf}
-\logo [WDT] {wdt}
-\logo [WEB] {web}
-\logo [WEBC] {web2c}
-\logo [WIKI] {Wiki}
-\logo [WINDOWS] {Windows}
-\logo [WINNT] {WinNT}
-\logo [WINNX] {Win9x}
-\logo [WWW] {www}
-\logo [WTHREEC] {W3C}
-\logo [WYSIWYG] {wysiwyg}
-\logo [XDVI] {Xdvi}
-\logo [XETEX] {\XeTeX}
-\logo [XFDF] {xfdf}
-\logo [XHTML] {xhtml}
-\logo [XINDY] {Xindy}
-\logo [XML] {xml}
-\logo [XPATH] {xpath}
-\logo [XMLTOOLS] {xmltools}
-\logo [XPDFETEX] {xpdfe\TeX}
-\logo [XSL] {xsl}
-\logo [XSLFO] {xsl-fo}
-\logo [XSLT] {xslt}
-\logo [XSLTPROC] {xsltproc}
-\logo [XYPIC] {XYPIC} % wrong logo
-\logo [YandY] {y\&y}
-\logo [ZIP] {zip}
+\logo [EUROMATH] {EuroMath}
+\logo [EUROTEX] {Euro\TeX}
+\logo [EXAMPLE] {eXaMpLe}
+\logo [EXAMPLED] {exampled}
+\logo [EXAMPLEQ] {exampleq}
+\logo [EXAMPLER] {exampler}
+\logo [EXAMPLET] {examplet}
+\logo [EXAMPLEX] {examplex}
+\logo [EXIMPLE] {eXiMpLe}
+\logo [FLAC] {flac}
+\logo [FAQ] {faq}
+\logo [FDF] {fdf}
+\logo [FONTFORGE] {FontForge}
+\logo [FOXET] {foXet}
+\logo [FPTEX] {fp\TeX}
+\logo [FREEBSD] {FreeBSD}
+\logo [FTP] {ftp}
+\logo [GHOSTSCRIPT] {Ghost\-script}
+\logo [GHOSTVIEW] {Ghost\-view}
+\logo [GIF] {gif}
+\logo [GNU] {gnu}
+\logo [GNUPLOT] {gnuplot}
+\logo [GS] {Ghost\-Script}
+\logo [GUST] {Gust}
+\logo [GCC] {gcc}
+\logo [GWTEX] {gw\TeX}
+\logo [HSB] {hsb}
+\logo [HTML] {html}
+\logo [HTTP] {http}
+\logo [HZ] {hz}
+\logo [IBM] {ibm}
+\logo [IMAGEMAGICK] {ImageMagick}
+\logo [INITEX] {ini\TeX}
+\logo [INRSTEX] {inrs\TeX}
+\logo [IO] {io}
+\logo [IRCNET] {IRCnet}
+\logo [ISO] {iso}
+\logo [JAVA] {Java}
+\logo [JAVASCRIPT] {Java\-Script}
+\logo [JPEG] {jpeg}
+\logo [JPG] {jpg}
+\logo [KPATHSEA] {kpathsea}
+\logo [KPSE] {kpse}
+\logo [KPSEWHICH] {kpsewhich}
+\logo [MKTEXLSR] {mktexlsr}
+\logo [MYSQL] {MySQL}
+\logo [LAMSTEX] {\LamSTeX}
+\logo [LATEX] {\LaTeX}
+\logo [LATEXTE] {\LaTeX2e}
+\logo [LATEXTN] {\LaTeX2.09}
+\logo [LCD] {lcd}
+\logo [LINUX] {linux}
+\logo [LISP] {Lisp}
+\logo [LPEG] {lpeg}
+\logo [LUA] {Lua}
+\logo [LUAJIT] {LuaJIT}
+\logo [LUATEX] {Lua\TeX}
+\logo [LUATOOLS] {luatools}
+\logo [LMX] {lmx}
+\logo [MACOSX] {MacOSX}
+\logo [MACROTEX] {Macro\TeX}
+\logo [MAKEMPY] {MakeMPY}
+\logo [MAPPING] {map}
+\logo [MAPS] {Maps}
+\logo [MATHML] {MathML}
+\logo [METAFONT] {\MetaFont}
+\logo [METAPOST] {\MetaPost}
+\logo [METATEX] {Meta\TeX}
+\logo [MIKTEX] {Mik\TeX}
+\logo [MINGW] {MingW}
+\logo [MLTEX] {ml\TeX}
+\logo [METATYPE] {MetaType1}
+\logo [MODULA] {Modula}
+\logo [MOV] {mov}
+\logo [MPS] {mps}
+\logo [MPTOPDF] {mptopdf}
+\logo [MPLIB] {mplib}
+\logo [MSDOS] {msdos}
+\logo [MICROSOFT] {Microsoft}
+\logo [MSWINDOWS] {MS~Windows}
+\logo [MSWORD] {MS~Word}
+\logo [MTXRUN] {mtxrun}
+\logo [MTXTOOLS] {mtxtools}
+\logo [NETPBM] {NetPBM}
+\logo [NTG] {ntg}
+\logo [NTS] {nts}
+\logo [OFM] {ofm}
+\logo [OMEGA] {Omega}
+\logo [OPENMATH] {OpenMath}
+\logo [OPENTYPE] {OpenType}
+\logo [OPI] {opi}
+\logo [OTEX] {Oriental \TeX}
+\logo [OTF] {otf}
+\logo [OTP] {otp}
+\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}
+\logo [PDFTOOLS] {pdftools}
+\logo [PDFTOPS] {pdftops}
+\logo [PERL] {Perl}
+\logo [PERLTK] {Perl/Tk}
+\logo [PICTEX] {\PiCTeX}
+\logo [PK] {pk}
+\logo [PLAIN] {Plain}
+\logo [PNG] {png}
+\logo [POSIX] {posix}
+\logo [POSTSCRIPT] {Post\-Script}
+\logo [PPCHTEX] {\PPCHTeX}
+\logo [PRAGMA] {Pragma ADE}
+\logo [PRESS] {press}
+\logo [PRIFIL] {prifil}
+\logo [PS] {Post\-Script}
+\logo [PSCHECK] {pscheck}
+\logo [PSTOEDIT] {pstoedit}
+\logo [PSTOPAGE] {pstopage}
+\logo [PSTOPDF] {pstopdf}
+\logo [PSTRICKS] {pstricks}
+\logo [RAM] {ram}
+\logo [READER] {Acro\-bat Reader}
+\logo [RELAXNG] {Relax\kern.125emNG}
+\logo [RGB] {rgb}
+\logo [RLXTOOLS] {rlxtools}
+\logo [RUBY] {Ruby}
+\logo [SCITE] {SciTE}
+\logo [SGML] {sgml}
+\logo [SI] {si}
+\logo [SQL] {sql}
+\logo [SVG] {svg}
+\logo [SWIG] {swig}
+\logo [TABLE] {\TaBlE}
+\logo [TCPIP] {tcp/ip}
+\logo [TDS] {tds} % no sc te
+\logo [TETEX] {te\TeX} % no sc te
+\logo [TEX] {\TeX}
+\logo [TEXADRES] {\TeX adress}
+\logo [TEXBASE] {\TeX base}
+\logo [TEXEDIT] {\TeX edit}
+\logo [TEXEXEC] {\TeX exec}
+\logo [TEXFONT] {\TeX font}
+\logo [TEXFORM] {\TeX form}
+\logo [TEXLIVE] {\TeX Live}
+\logo [TEXLUA] {\TeX Lua}
+\logo [TEXMF] {texmf}
+\logo [TEXMFSTART] {texmfstart}
+\logo [TEXNL] {tex-nl}
+\logo [TEXSHOW] {\TeX show}
+\logo [TEXSPELL] {\TeX spell}
+\logo [TEXGYRE] {\TeX\ Gyre}
+\logo [TEXSYNC] {texsync}
+\logo [TEXTMATE] {TextMate}
+\logo [TEXTOOLS] {\TeX tools}
+\logo [TEXUTIL] {\TeX util}
+\logo [TEXWORK] {\TeX work}
+\logo [TEXXET] {\TeX\XeT} \def\XeT{XeT}
+\logo [TFM] {tfm}
+\logo [TIF] {tif}
+\logo [TIFF] {tiff}
+\logo [TIFFINFO] {tiffinfo}
+\logo [TIFFTAGS] {tifftags}
+\logo [TMFTOOLS] {tmftools}
+\logo [TPIC] {tpic}
+\logo [TPM] {tpm}
+\logo [TRUETYPE] {TrueType}
+\logo [TTC] {ttc}
+\logo [TTF] {ttf}
+\logo [TUG] {tug}
+\logo [TUGBOAT] {Tug\-Boat}
+\logo [TUGNEWS] {Tug\-News}
+\logo [TYPEONE] {Type1}
+\logo [UCS] {ucs}
+\logo [UNICODE] {Uni\-code}
+\logo [UNIX] {Unix}
+\logo [URI] {uri}
+\logo [URL] {url}
+\logo [USA] {usa}
+\logo [USENET] {usenet}
+\logo [UTF] {utf}
+\logo [USB] {usb}
+\logo [VF] {vf}
+\logo [WDT] {wdt}
+\logo [WEB] {web}
+\logo [WEBC] {web2c}
+\logo [WIKI] {Wiki}
+\logo [WINDOWS] {Windows}
+\logo [WINNT] {WinNT}
+\logo [WINNX] {Win9x}
+\logo [WWW] {www}
+\logo [WTHREEC] {W3C}
+\logo [WYSIWYG] {wysiwyg}
+\logo [XDVI] {Xdvi}
+\logo [XETEX] {\XeTeX}
+\logo [XFDF] {xfdf}
+\logo [XHTML] {xhtml}
+\logo [XINDY] {Xindy}
+\logo [XML] {xml}
+\logo [XPATH] {xpath}
+\logo [XMLTOOLS] {xmltools}
+\logo [XPDFETEX] {xpdfe\TeX}
+\logo [XSL] {xsl}
+\logo [XSLFO] {xsl-fo}
+\logo [XSLT] {xslt}
+\logo [XSLTPROC] {xsltproc}
+\logo [XYPIC] {XYPIC} % wrong logo
+\logo [YandY] {y\&y}
+\logo [ZIP] {zip}
\def\METAFUN {\MetaFun}
diff --git a/tex/context/base/s-art-01.mkiv b/tex/context/base/s-art-01.mkiv
index 10b4de9ab..c8d849d8c 100644
--- a/tex/context/base/s-art-01.mkiv
+++ b/tex/context/base/s-art-01.mkiv
@@ -2,6 +2,8 @@
% \showframe
+\unprotect
+
\setuplayout
[\c!topspace=2cm,
\c!bottomspace=2.5cm,
@@ -33,4 +35,6 @@
[\c!style=\bf,
\c!after=]
+\protect
+
\stopmodule
diff --git a/tex/context/base/s-def-01.mkiv b/tex/context/base/s-def-01.mkiv
index 1c8ee9469..49e585bd0 100644
--- a/tex/context/base/s-def-01.mkiv
+++ b/tex/context/base/s-def-01.mkiv
@@ -4,7 +4,7 @@
\startsetups defaults:frontpart:pagenumbers:roman
\defineconversionset[\c!frontpart:\c!pagenumber][][romannumerals]
- \setupuserpagenumber[\c!way=\v!byblock]
+ \setupuserpagenumber[\c!way=\v!by\v!block]
\stopsetups
\protect
diff --git a/tex/context/base/s-fnt-10.mkiv b/tex/context/base/s-fnt-10.mkiv
index 0d4a608a4..0edb19120 100644
--- a/tex/context/base/s-fnt-10.mkiv
+++ b/tex/context/base/s-fnt-10.mkiv
@@ -135,7 +135,7 @@ end
\page
\egroup}
-\doifnotmode{demo} {\endinput}
+\continueifinputfile{s-fnt-10.mkiv}
\starttext
diff --git a/tex/context/base/s-fnt-20.mkiv b/tex/context/base/s-fnt-20.mkiv
index a78f62555..54ed419c0 100644
--- a/tex/context/base/s-fnt-20.mkiv
+++ b/tex/context/base/s-fnt-20.mkiv
@@ -85,10 +85,10 @@
rlig=yes,liga=yes,dlig=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}
+\setvalue{otftracker-direction-arabtype}{r2l}
+\setvalue{otftracker-direction-husayni}{r2l}
+\setvalue{otftracker-direction-simplenaskhi}{r2l}
+\setvalue{otftracker-direction-default}{}
\setvariables
[otftracker]
@@ -129,7 +129,7 @@
\chapter{\getvariable{otftracker}{title}}
\doifsomething {\getvariable{otftracker}{figure}} {
\startlinecorrection
- \externalfigure[\getvariable{otftracker}{figure}]
+ \externalfigure[\getvariable{otftracker}{figure}][maxwidth=\hsize,frame=on]
\stoplinecorrection
}
\showotfcomposition
diff --git a/tex/context/base/s-fnt-28.mkiv b/tex/context/base/s-fnt-28.mkiv
index 039cc6ca8..778a4c390 100644
--- a/tex/context/base/s-fnt-28.mkiv
+++ b/tex/context/base/s-fnt-28.mkiv
@@ -35,7 +35,7 @@
end
\stopluacode
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-fnt-28.mkiv}
\starttext
diff --git a/tex/context/base/s-fnt-29.mkiv b/tex/context/base/s-fnt-29.mkiv
index 0378550e8..f9e0a1658 100644
--- a/tex/context/base/s-fnt-29.mkiv
+++ b/tex/context/base/s-fnt-29.mkiv
@@ -48,7 +48,7 @@
\stopluacode
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-fnt-29.mkiv}
\setupbodyfont[dejavu,tt,9pt]
diff --git a/tex/context/base/s-fnt-32.mkiv b/tex/context/base/s-fnt-32.mkiv
index 5ffbb2ac5..20a939a97 100644
--- a/tex/context/base/s-fnt-32.mkiv
+++ b/tex/context/base/s-fnt-32.mkiv
@@ -30,7 +30,7 @@
end
\stopluacode
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-fnt-32.mkiv}
\setupbodyfont[dejavu,10pt]
diff --git a/tex/context/base/s-inf-01.mkvi b/tex/context/base/s-inf-01.mkvi
index 51d3cbac8..b3f44e908 100644
--- a/tex/context/base/s-inf-01.mkvi
+++ b/tex/context/base/s-inf-01.mkvi
@@ -226,7 +226,7 @@
\stopTEXpage
\stoptexdefinition
-% \doifnotmode{demo}{\endinput}
+% \continueifinputfile{s-inf-01.mkvi}
\starttext
\Show
diff --git a/tex/context/base/s-inf-03.mkiv b/tex/context/base/s-inf-03.mkiv
index 1ff4cd0d0..e2428ce5e 100644
--- a/tex/context/base/s-inf-03.mkiv
+++ b/tex/context/base/s-inf-03.mkiv
@@ -1,6 +1,12 @@
% \nopdfcompression
-\enablemode[ipad]
+% \starttext
+% There is a loop somewhere ... todo.
+% \stoptext
+
+\enablemode[ipad] % whatever that means
+
+\setupbodyfont[dejavu]
\doifmodeelse {ipad} {
@@ -10,16 +16,16 @@
\definefont
[TitlePageFont]
- [MonoBold at 18pt]
+ [MonoBold at 16pt]
\setupbodyfont
- [tt,10pt]
+ [tt,8pt]
} {
\definefont
[TitlePageFont]
- [MonoBold at 24pt]
+ [MonoBold at 20pt]
\setupbodyfont
[tt]
@@ -231,7 +237,6 @@ end
local function handler(k,t,depth)
k = gsub(k,"([~#$%%^&{}\\\|])",cleanup)
--- NC() rlap("\\quad\\tx " .. upper(sub(t,1,1)) .. " ".. k) NC() NC() NR()
NC() rlap("\\quad\\tx\\kern" .. (depth or 0).. "em" .. upper(sub(t,1,1)) .. " ".. k) NC() NC() NR()
end
@@ -260,67 +265,65 @@ local function show(title,subtitle,alias,builtin,t,lib,libcolor,glo,glocolor,mar
for i=1,#keys do
local k = keys[i]
local v = t[k]
- if k ~= "obsolete" and not skipkeys[k] and (not obsolete or not obsolete[k]) then
+ if k and k ~= "obsolete" and not skipkeys[k] and (not obsolete or not obsolete[k]) then
local inlib = lib and lib[k]
local inglo = glo and glo[k]
- if k then
- local t = type(v)
- local kstr, tstr = k, t
- local obs = t_obsolete and t_obsolete[k]
- if obs then
- tstr = function() overstrike(t) end
- kstr = function() overstrike(k) end
- end
- local marked = marked(v)
- if marked then
- tstr = "data table"
- end
- if t == "table" then
- local m = getmetatable(v)
- if m and m.__call then
- tstr = "function"
- end
- end
- if not mark then
- --
- elseif inlib and tostring(inlib) ~= tostring(v) then
- tstr = "overloaded ".. tstr
- elseif inglo and tostring(inglo) ~= tostring(v) then
- tstr = "overloaded ".. tstr
+ local t = type(v)
+ local kstr, tstr = k, t
+ local obs = t_obsolete and t_obsolete[k]
+ if obs then
+ tstr = function() overstrike(t) end
+ kstr = function() overstrike(k) end
+ end
+ local marked = marked(v)
+ if marked then
+ tstr = "data table"
+ end
+ if t == "table" then
+ local m = getmetatable(v)
+ if m and m.__call then
+ tstr = "function"
end
- NC() bf()
- if inlib then
- if not mark and t == "table" then
- goto(function() color( { libcolor }, kstr) end, { k } )
- else
- color( { libcolor }, kstr)
- end
- elseif inglo then
- if not mark and t == "table" then
- goto(function() color( { glocolor }, kstr) end, { k } )
- else
- color( { glocolor }, kstr)
- end
+ end
+ if not mark then
+ --
+ elseif inlib and tostring(inlib) ~= tostring(v) then
+ tstr = "overloaded ".. tstr
+ elseif inglo and tostring(inglo) ~= tostring(v) then
+ tstr = "overloaded ".. tstr
+ end
+ NC() bf()
+ if inlib then
+ if not mark and t == "table" then
+ goto(function() color( { libcolor }, kstr) end, { k } )
else
- if not mark and t == "table" then
- goto(k, { kstr } )
- else
- context(kstr)
- end
+ color( { libcolor }, kstr)
end
- NC()
- if inlib then
- color( { libcolor }, tstr)
- elseif inglo then
- color( { glocolor }, tstr)
+ elseif inglo then
+ if not mark and t == "table" then
+ goto(function() color( { glocolor }, kstr) end, { k } )
else
- context(tstr)
+ color( { glocolor }, kstr)
end
- NC() NR()
- if mark and t == "table" and title ~= "libraries" and title ~= "package" and not marked then
- childtables(false,v,handler) -- (k,v,handler)
+ else
+ if not mark and t == "table" then
+ goto(k, { kstr } )
+ else
+ context(kstr)
end
end
+ NC()
+ if inlib then
+ color( { libcolor }, tstr)
+ elseif inglo then
+ color( { glocolor }, tstr)
+ else
+ context(tstr)
+ end
+ NC() NR()
+ if mark and t == "table" and title ~= "libraries" and title ~= "package" and not marked then
+ childtables(false,v,handler) -- (k,v,handler)
+ end
end
end
context.stoptabulate()
diff --git a/tex/context/base/s-lan-04.mkiv b/tex/context/base/s-lan-04.mkiv
index 80283bfd4..c04be9466 100644
--- a/tex/context/base/s-lan-04.mkiv
+++ b/tex/context/base/s-lan-04.mkiv
@@ -138,7 +138,7 @@
\definecolor[hyphenation:de] [g=.8]
\definecolor[hyphenation:nl] [b=.8]
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-lan-04.mkiv}
\starttext
diff --git a/tex/context/base/s-mod.ctx b/tex/context/base/s-mod.ctx
index 5059c77d4..09ecf714c 100644
--- a/tex/context/base/s-mod.ctx
+++ b/tex/context/base/s-mod.ctx
@@ -11,7 +11,6 @@
</ctx:files>
</ctx:preprocess>
<ctx:flags>
- <!-- ctx:flag>purge</ctx:flag -->
<ctx:flag>global</ctx:flag>
<ctx:flag>prep</ctx:flag>
<ctx:flag>purge</ctx:flag>
diff --git a/tex/context/base/s-pre-60.mkiv b/tex/context/base/s-pre-60.mkiv
index b39a06311..70f8978b0 100644
--- a/tex/context/base/s-pre-60.mkiv
+++ b/tex/context/base/s-pre-60.mkiv
@@ -13,6 +13,8 @@
% use lua instead of global mess
+\unprotect
+
\startmode[paper,print]
\let\StartSteps\relax
\let\StopSteps \relax
@@ -23,22 +25,31 @@
\endinput
\stopmode
-\newcounter\StepCounter
-\newcounter\StepMaximum
+\newcount\c_module_pre_steps_current
+\newcount\c_module_pre_steps_maximum
+\newcount\c_module_pre_steps_nesting_step
+\newcount\c_module_pre_steps_nesting_steps
+\newcount\c_module_pre_steps_nesting_busy
+
+\def\StepCounter {\the\c_module_pre_steps_current}
+\def\StepMaximum {\the\c_module_pre_steps_maximum}
+\def\StepLayer {step:\the\c_module_pre_steps_current}
+\def\NextStepLayer {step:\the\numexpr\c_module_pre_steps_current+\plusone\relax}
+\def\FirstStepLayer{step:1}
\useJSscripts[stp]
\startsetups[set-stepper]
- \ifnum\getvariable{stepper}{nofsteps}>\StepMaximum
+ \ifnum\getvariable{stepper}{nofsteps}>\c_module_pre_steps_maximum
- \dostepwiserecurse {\numexpr\StepMaximum+1\relax} {\getvariable{stepper}{nofsteps}} {1} {
+ \dostepwiserecurse {\numexpr\c_module_pre_steps_maximum+\plusone\relax} {\getvariable{stepper}{nofsteps}} {1} {
\doifnotmode{nosteps,nostep} {
\expanded{\defineviewerlayer[step:\recurselevel][state=stop,scope=global]}
}
}
- \xdef\StepMaximum{\getvariable{stepper}{nofsteps}}
+ \global\c_module_pre_steps_maximum\getvariable{stepper}{nofsteps}\relax
\fi
@@ -58,25 +69,100 @@
% todo: roll back blank
-\def\ResetStep {\doglobal\newcounter\StepCounter}
-\def\NextStep {\doglobal\increment \StepCounter}
-\def\PrevStep {\doglobal\decrement \StepCounter}
+\unexpanded\def\ResetStep
+ {\iftrialtypesetting\else
+ \global\c_module_pre_steps_current\zerocount
+ \fi}
+
+\unexpanded\def\NextStep
+ {\iftrialtypesetting\else
+ \global\advance\c_module_pre_steps_current\plusone
+ \fi}
+
+\unexpanded\def\PrevStep
+ {\iftrialtypesetting\else
+ \global\advance\c_module_pre_steps_current\minusone
+ \fi}
+
+\unexpanded\def\FlushStep
+ {\iftrialtypesetting\else
+ \StopStep
+ \NextStep
+ \StartStep
+ \fi}
+
+\unexpanded\def\StartStep
+ {\iftrialtypesetting\else
+ \global\advance\c_module_pre_steps_nesting_step\plusone
+ \ifcase\c_module_pre_steps_nesting_step\or
+ \startviewerlayer[\StepLayer]%
+ \fi
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\StopStep
+ {\removeunwantedspaces
+ \iftrialtypesetting\else
+ \ifcase\c_module_pre_steps_nesting_step\or
+ \stopviewerlayer
+ \fi
+ \global\advance\c_module_pre_steps_nesting_step\minusone
+ \fi}
+
+\unexpanded\def\StartSteps
+ {\iftrialtypesetting\else
+ \global\advance\c_module_pre_steps_nesting_steps\plusone
+ \ifcase\c_module_pre_steps_nesting_steps\or
+ \ResetStep
+ \NextStep
+ \StartStep
+ \fi
+ \fi}
+
+\unexpanded\def\StopSteps
+ {\iftrialtypesetting\else
+ \ifcase\c_module_pre_steps_nesting_steps\or
+ \StopStep
+ \PrevStep
+ \fi
+ \global\advance\c_module_pre_steps_nesting_steps\minusone
+ \fi}
+
+\unexpanded\def\StartBusy
+ {\iftrialtypesetting\else
+ \global\advance\c_module_pre_steps_nesting_busy\plusone
+ \ifcase\c_module_pre_steps_nesting_busy\or
+ \startviewerlayer[step:busy]
+ \fi
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\StopBusy
+ {\removeunwantedspaces
+ \iftrialtypesetting\else
+ \ifcase\c_module_pre_steps_nesting_busy\or
+ \stopviewerlayer
+ \fi
+ \global\advance\c_module_pre_steps_nesting_busy\minusone
+ \fi}
-\def\StepLayer {step:\StepCounter}
-\def\NextStepLayer {step:\the\numexpr\StepCounter+1\relax}
-\def\FirstStepLayer{step:1}
+%D Handy:
+
+\unexpanded\def\StartLocalSteps
+ {\ResetStep}
-\def\StartStep {\startviewerlayer[\StepLayer]\ignorespaces}
-\def\StopStep {\removeunwantedspaces\stopviewerlayer}
-\def\StartSteps {\iftrialtypesetting\else\ResetStep\NextStep\StartStep\fi}
-\def\StopSteps {\iftrialtypesetting\else\StopStep \PrevStep \fi}
-\def\FlushStep {\iftrialtypesetting\else\StopStep \NextStep\StartStep\fi}
+\unexpanded\def\StopLocalSteps
+ {}
-\def\StartBusy {\startviewerlayer[step:busy]\ignorespaces}
-\def\StopBusy {\removeunwantedspaces\stopviewerlayer}
+\unexpanded\def\StartLocalStep
+ {\NextStep
+ \StartStep}
+
+\unexpanded\def\StopLocalStep
+ {\StopStep}
\appendtoks
- \ResetStep
+ \ResetStep
\to \everyaftershipout
\setupinteraction
@@ -112,14 +198,6 @@
[symbol={attach-normal,attach-down},
textlayer=\StepLayer]
-%D Handy:
-
-\def\StartLocalSteps{\ResetStep}
-\def\StopLocalSteps {}
-
-\def\StartLocalStep {\NextStep\StartStep}
-\def\StopLocalStep {\StopStep}
-
%D used as (given some definitions):
%D
%D \starttyping
@@ -131,4 +209,4 @@
%D \StopLocalSteps
%D \stoptyping
-\endinput
+\protect \endinput
diff --git a/tex/context/base/s-pre-61.tex b/tex/context/base/s-pre-61.tex
index 21e461320..ea221fbcb 100644
--- a/tex/context/base/s-pre-61.tex
+++ b/tex/context/base/s-pre-61.tex
@@ -16,7 +16,7 @@
\usemodule[pre-60]
\doifmodeelse {mkiv} {
- \usetypescriptfile[type-hgz]
+ \usetypescriptfile[ghz]
\definetypeface[mainface][ss][sans][optima-nova][default]
} {
\usetypescriptfile[type-ghz]
diff --git a/tex/context/base/s-pre-62.tex b/tex/context/base/s-pre-62.tex
index cc9762e12..a1a405c23 100644
--- a/tex/context/base/s-pre-62.tex
+++ b/tex/context/base/s-pre-62.tex
@@ -220,5 +220,5 @@
\long\def\StartTitlePage #1\StopTitlePage {\TitlePage {#1}}
\long\def\StartSubTitlePage#1\StopSubTitlePage{\SubTitlePage{#1}}
-\doifnotmode{demo} {\endinput}
+\endinput
diff --git a/tex/context/base/s-pre-63.tex b/tex/context/base/s-pre-63.tex
index 0535fc1d0..974c67a5f 100644
--- a/tex/context/base/s-pre-63.tex
+++ b/tex/context/base/s-pre-63.tex
@@ -67,6 +67,7 @@ this module is under reconstruction
\setupbodyfont[8pt] \definefont[BigFont][Normal sa 4]
\starttext
+
\StartPage
\StartPair \StartLeft ZAPF \StopLeft \StartRight \input zapf \StopRight \StopPair
\StartPair \StartLeft DAVIS \StopLeft \StartRight \input davis \StopRight \StopPair
diff --git a/tex/context/base/s-pre-67.tex b/tex/context/base/s-pre-67.tex
index 88043aa24..84ea1a66c 100644
--- a/tex/context/base/s-pre-67.tex
+++ b/tex/context/base/s-pre-67.tex
@@ -119,7 +119,7 @@
\setupwhitespace
[big]
-\def\MyCommand#1#2%
+\unexpanded\def\MyCommand#1#2%
{\setlayer[title][preset=rightbottom,x=.75cm,y=.5cm]{#2}}
\def\titlepage#1#2%
diff --git a/tex/context/base/s-pre-69.mkiv b/tex/context/base/s-pre-69.mkiv
index c87bcd537..cc6af9ad3 100644
--- a/tex/context/base/s-pre-69.mkiv
+++ b/tex/context/base/s-pre-69.mkiv
@@ -311,7 +311,7 @@
\setelementexporttag[paragraphs][nature][display]
\setelementexporttag[paragraph] [nature][mixed]
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-pre-69.mkiv}
% finetuning: \StartText{\TEX\ and Reality\vskip2exClashing Mindsets?\vskip1ex}{Bacho\TEX, May 1, 2010}
diff --git a/tex/context/base/scrn-fld.lua b/tex/context/base/scrn-fld.lua
index 275fb4a9b..9836cbebe 100644
--- a/tex/context/base/scrn-fld.lua
+++ b/tex/context/base/scrn-fld.lua
@@ -73,13 +73,13 @@ function commands.setformsmethod(method)
end
function commands.doiffieldcategoryelse(name)
- commands.testcase(codeinjections.validfieldcategory(name))
+ commands.doifelse(codeinjections.validfieldcategory(name))
end
function commands.doiffieldsetelse(tag)
- commands.testcase(codeinjections.validfieldset(name))
+ commands.doifelse(codeinjections.validfieldset(name))
end
function commands.doiffieldelse(name)
- commands.testcase(codeinjections.validfield(name))
+ commands.doifelse(codeinjections.validfield(name))
end
diff --git a/tex/context/base/scrn-fld.mkvi b/tex/context/base/scrn-fld.mkvi
index 872099099..a811c6481 100644
--- a/tex/context/base/scrn-fld.mkvi
+++ b/tex/context/base/scrn-fld.mkvi
@@ -403,7 +403,7 @@
\setupfieldcontentframed
[\c!align=\v!flushleft,
\c!strut=\v!no,
- \s!parent=\??ol] % needs checking
+ \s!parent=\??regularframed] % needs checking
\setupfieldcontentframed % independent
[\c!alternative=\v!normal,
@@ -419,13 +419,13 @@
[\c!style=,
\c!color=,
\c!align=\v!flushleft,
- \s!parent=\??ol] % needs checking
+ \s!parent=\??regularframed] % needs checking
\setupfieldtotalframed
[%\c!alternative={\v!label,\v!frame,\v!horizontal},
\c!strut=\v!no,
\c!align=,
- \s!parent=\??ol] % needs checking
+ \s!parent=\??regularframed] % needs checking
% \setupcurrent
@@ -616,9 +616,9 @@
\v!horizontal=>\settrue\fieldishorizontal,
\v!vertical=>\settrue\fieldisvertical]%
\ifconditional\fieldisvertical
- \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=\vskip\@@localoffset,\c!align=\v!right,\c!width=20em]%
+ \setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=\vskip\d_framed_local_offset,\c!align=\v!right,\c!width=20em]%
\else\ifconditional\fieldishorizontal
- \setupfieldtotalframed[\c!distance=\@@localoffset,\c!inbetween=,\c!align=\c!left,\c!height=10ex]%
+ \setupfieldtotalframed[\c!distance=\d_framed_local_offset,\c!inbetween=,\c!align=\c!left,\c!height=10ex]%
\else
\setupfieldtotalframed[\c!distance=\zeropoint,\c!inbetween=,\c!align=\c!left]%
\fi\fi
diff --git a/tex/context/base/scrn-ini.lua b/tex/context/base/scrn-ini.lua
index 2836362df..8fe1e0cae 100644
--- a/tex/context/base/scrn-ini.lua
+++ b/tex/context/base/scrn-ini.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['scrn-int'] = {
+if not modules then modules = { } end modules ['scrn-ini'] = {
version = 1.001,
comment = "companion to scrn-int.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/tex/context/base/scrn-ini.mkvi b/tex/context/base/scrn-ini.mkvi
index daf0a1b91..a6cb495ee 100644
--- a/tex/context/base/scrn-ini.mkvi
+++ b/tex/context/base/scrn-ini.mkvi
@@ -144,16 +144,16 @@
\useinteractionstyleandcolor\c!style\c!color
\fi}
-\unexpanded\def\setlocationcolorspec#1#2% \resolver
+\unexpanded\def\setlocationcolorspecspecified#1#2% \resolver
{\ifnum#1=\plusone
\edef\askedcontrastcolor{#2\c!contrastcolor}%
\ifx\askedcontrastcolor\empty
- \doactivatecolor{#2\c!color}%
+ \colo_helpers_activate{#2\c!color}%
\else
- \doactivatecolor\askedcontrastcolor
+ \colo_helpers_activate\askedcontrastcolor
\fi
\else
- \doactivatecolor{#2\c!color}%
+ \colo_helpers_activate{#2\c!color}%
\fi}
\unexpanded\def\setlocationcolor {\setlocationcolorspecified \referencepagestate}
@@ -184,9 +184,11 @@
\scrn_identity_synchronize
\to \everysetupinteraction
+% this comes before starttext
+
\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: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
diff --git a/tex/context/base/scrn-pag.mkvi b/tex/context/base/scrn-pag.mkvi
index 66f197ffd..5bbdadda8 100644
--- a/tex/context/base/scrn-pag.mkvi
+++ b/tex/context/base/scrn-pag.mkvi
@@ -150,12 +150,6 @@
{\global\setfalse\c_scrn_canvas_tight_page}%
\to \everysetupinteractionscreen
-\appendtoks
- \doifelse\@@pcstate\v!start
- \scrn_canvas_synchronize_simple
- \scrn_canvas_synchronize_complex
-\to \everyshipout
-
\setupinteractionscreen
[\c!width=\printpaperwidth,
\c!height=\printpaperheight,
diff --git a/tex/context/base/scrn-ref.lua b/tex/context/base/scrn-ref.lua
index 0b1dff2c1..df71b6a97 100644
--- a/tex/context/base/scrn-ref.lua
+++ b/tex/context/base/scrn-ref.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['scrn-int'] = {
+if not modules then modules = { } end modules ['scrn-ref'] = {
version = 1.001,
comment = "companion to scrn-int.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/tex/context/base/scrn-wid.lua b/tex/context/base/scrn-wid.lua
index 6fdc4fca0..14d58a29a 100644
--- a/tex/context/base/scrn-wid.lua
+++ b/tex/context/base/scrn-wid.lua
@@ -167,11 +167,19 @@ function renderings.rendering(label)
end
end
-function renderings.var(label,key)
+local function var(label,key)
local rn = renderings[label]
- context(rn and rn[key] or "")
+ return rn and rn[key] or ""
end
+renderings.var = var
+
+function commands.renderingvar(label,key)
+ context(var(label,key))
+end
+
+commands.registerrendering = renderings.register
+
-- Rendering:
function commands.insertrenderingwindow(specification)
diff --git a/tex/context/base/scrn-wid.mkvi b/tex/context/base/scrn-wid.mkvi
index 2b75f83cd..9b3f0cb78 100644
--- a/tex/context/base/scrn-wid.mkvi
+++ b/tex/context/base/scrn-wid.mkvi
@@ -421,7 +421,7 @@
\doifassignmentelse{#title}
{\setupcurrentcomment[#title]}
{\setupcurrentcomment[\c!title=#title,#settings]}%
- \def\scrn_comment_stop{\scrn_comment_inject\egroup}%
+ \unexpanded\def\scrn_comment_stop{\scrn_comment_inject\egroup}%
\grabbufferdatadirect\v!comment{\e!start\currentcomment}{\e!stop\currentcomment}}
\def\scrn_comment_start_ignore
@@ -432,7 +432,7 @@
\installcorenamespace{commentmethods}
-\def\scrn_comment_inject
+\unexpanded\def\scrn_comment_inject
{\expandcheckedcsname\??commentmethods{\commentparameter\c!method}\v!normal}
%D Beware: comments symbols don't scale in acrobat (cf. spec but somewhat
@@ -476,35 +476,34 @@
\wd\b_scrn_comment_link\currentcommentwidth
\ht\b_scrn_comment_link\currentcommentheight
\dp\b_scrn_comment_link\currentcommentdepth
- \scrn_comment_place}
+ \expandcheckedcsname\??commentlocation{\commentparameter\c!location}\s!unknown}
\setvalue{\??commentmethods\v!hidden}%
{}
% todo: dedicated margin classes
-\def\scrn_comment_place
- {\executeifdefined
- {\??commentlocation\commentparameter\c!location}\hbox
- {\hbox{\box\b_scrn_comment_link}}}
-
-\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%
+\setvalue{\??commentlocation\v!inmargin }{\inmargin {\box\b_scrn_comment_link}}
+\setvalue{\??commentlocation\v!leftedge }{\inleftedge {\box\b_scrn_comment_link}}
+\setvalue{\??commentlocation\v!rightedge }{\inrightedge {\box\b_scrn_comment_link}}
+\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin {\box\b_scrn_comment_link}}
+\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin{\box\b_scrn_comment_link}}
+\setvalue{\??commentlocation\v!high }{\high {\box\b_scrn_comment_link}}
+
+\setvalue{\??commentlocation\v!none}%
{\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%
+ \box\b_scrn_comment_link
\egroup}
+\setvalue{\??commentlocation\s!unknown}%
+ {\ifvoid\b_scrn_comment_collect\else
+ \box\b_scrn_comment_collect
+ \fi}
+
\unexpanded\def\placecomments
{\ifvoid\b_scrn_comment_collect\else
\box\b_scrn_comment_collect
@@ -529,6 +528,13 @@
%D Todo: like external figures, also search on path,
%D although, they need to be present ar viewing time, so ...
+\installcorenamespace{externalsoundtracks}
+
+\installsetuponlycommandhandler \??externalsoundtracks {externalsoundtracks}
+
+\setupexternalsoundtracks
+ [\c!option=]
+
\unexpanded\def\useexternalsoundtrack
{\dodoubleargument\scrn_soundtrack_indeed}
@@ -541,17 +547,11 @@
\def\checksoundtrack#tag% yet untested in mkiv (also move management to lua)
{\iflocation
\ctxcommand{insertsoundclip{
- tag = "#tag",
- repeat = "\@@sdoption", % not entirely ok but works
+ tag = "#tag",
+ ["repeat"] = "\directexternalsoundtrackparameter\c!option", % todo: pass option as-is
}}%
\fi}
-\unexpanded\def\setupexternalsoundtracks
- {\dodoubleargument\getparameters[\??sd]}
-
-\setupexternalsoundtracks
- [\c!option=]
-
%D Renderings (not yet tested in mkvi):
% Todo: multiple instances and inheritance .. will be done when
@@ -568,7 +568,7 @@
\def\setinternalrendering{\dodoubleempty \scrn_rendering_set}
\def\scrn_rendering_use[#tag][#mime][#file][#option]%
- {\ctxlua{interactions.renderings.register {
+ {\ctxcommand{registerrendering{
type = "external",
label = "#tag",
mime = "#mime",
@@ -579,7 +579,7 @@
\def\scrn_rendering_set[#tag][#option]% {content}
{\bgroup
\dowithnextbox
- {\ctxlua{interactions.renderings.register {
+ {\ctxcommand{registerrendering{
type = "internal",
label = "#tag",
mime = "IRO", % brrr
@@ -591,28 +591,24 @@
\egroup}%
\hbox}
-\def\renderingtype #tag{\ctxlua{interactions.renderings.var("#tag","type")}}
-\def\renderingoption#tag{\ctxlua{interactions.renderings.var("#tag","option")}}
+\def\renderingtype #tag{\ctxcommand{renderingvar("#tag","type")}}
+\def\renderingoption#tag{\ctxcommand{renderingvar("#tag","option")}}
-\def\renderingwidth {8cm} % will become private
-\def\renderingheight{6cm} % will become private
+\newdimen\d_scrn_rendering_width \d_scrn_rendering_width 8cm
+\newdimen\d_scrn_rendering_height \d_scrn_rendering_height 6cm
-\unexpanded\def\definerenderingwindow
- {\dodoubleempty\scrn_rendering_define_window}
+\let\m_scrn_rendering_page\!!zerocount
-\def\scrn_rendering_define_window[#tag][#settings]%
- {\presetlocalframed[\??rw#tag]%
- \getparameters
- [\??rw#tag]%
- [\c!openpageaction=,\c!closepageaction=,%
- \c!width=\renderingwidth,\c!height=\renderingheight,%
- #settings]}
+\installcorenamespace{renderingwindow}
-\unexpanded\def\setuprenderingwindow
- {\dodoubleargument\scrn_rendering_setup_window}
+\installframedcommandhandler \??renderingwindow {renderingwindow} \??renderingwindow
-\def\scrn_rendering_setup_window[#tag]%
- {\getparameters[\??rw#tag]}
+\appendtoks
+ \letrenderingwindowparameter\c!openpageaction \empty
+ \letrenderingwindowparameter\c!closepageaction\empty
+ \setrenderingwindowparameter\c!width {\d_scrn_rendering_width }%
+ \setrenderingwindowparameter\c!height {\d_scrn_rendering_height}%
+\to \everypresetrenderingwindow
\unexpanded\def\placerenderingwindow
{\dodoubleempty\scrn_rendering_place_window}
@@ -622,31 +618,32 @@
\edef\currentrendering{\ifsecondargument#rendering\else#window\fi}%
\doifelse{\renderingtype\currentrendering}{internal} % an object
{\getobjectdimensions{IRO}\currentrendering
- \edef\renderingheight{\the\dimexpr\objectheight+\objectdepth\relax}%
- \edef\renderingwidth{\objectwidth}%
- \dogetobjectreferencepage{IRO}\currentrendering\renderingpage}%
- {\def\renderingheight{\vsize}%
- \def\renderingwidth{\hsize}%
- \def\renderingpage{\realpageno}}%
+ \d_scrn_rendering_height\dimexpr\objectheight+\objectdepth\relax
+ \d_scrn_rendering_width\objectwidth\relax
+ \dogetobjectreferencepage{IRO}\currentrendering\m_scrn_rendering_page}%
+ {\d_scrn_rendering_height\vsize
+ \d_scrn_rendering_width\hsize
+ \let\m_scrn_rendering_page\realpageno}%
% create fall back if needed
- \ifcsname\??rw#window\c!width\endcsname
- \def\currentrenderingwindow{#window}%
- \else
+ \edef\currentrenderingwindow{\namedrenderingwindowparameter{#window}\c!width}% stupid test, we need a proper one here
+ \ifx\currentrenderingwindow\empty
\let\currentrenderingwindow\s!default
- \definerenderingwindow[\currentrenderingwindow]%
+ \definerenderingwindow[\currentrenderingwindow]% why not global
+ \else
+ \edef\currentrenderingwindow{#window}%
\fi
-% todo
-% \handlereferenceactions{\getvalue{\??rw\currentrenderingwindow\c!openpageaction }}\dosetuprenderingopenpageaction
-% \handlereferenceactions{\getvalue{\??rw\currentrenderingwindow\c!closepageaction}}\dosetuprenderingclosepageaction
- \localframed
- [\??rw\currentrenderingwindow][\c!offset=\v!overlay]%
+ % todo:
+ % \handlereferenceactions{\renderingwindowparameter\c!openpageaction }\dosetuprenderingopenpageaction
+ % \handlereferenceactions{\renderingwindowparameter\c!closepageaction}\dosetuprenderingclosepageaction
+ \letrenderingwindowparameter\c!offset\v!overlay
+ \inheritedrenderingwindowframed
{\vfill
\ctxcommand{insertrenderingwindow {
label = "\currentrendering",
- width = \number\dimexpr\renderingwidth\relax,
- height = \number\dimexpr\renderingheight\relax,
+ width = \number\d_scrn_rendering_width,
+ height = \number\d_scrn_rendering_height,
option = "\renderingoption\currentrendering",
- page = \number\renderingpage,
+ page = \number\m_scrn_rendering_page,
}}\hfill}%
\egroup}
@@ -662,6 +659,8 @@
% %D \dorecurse{10}{\linkedlistelement[demo]{link \recurselevel} \page}
% %D \stoptyping
%
+% \definesystemvariable {lk} % LinK
+%
% \installcommandhandler\??lk{linkedlist}\??lk
%
% \let\setupbutton\setuplinkedlists\setuplinkedlist
diff --git a/tex/context/base/scrp-cjk.lua b/tex/context/base/scrp-cjk.lua
index 3463a8eb5..ab09ce9c8 100644
--- a/tex/context/base/scrp-cjk.lua
+++ b/tex/context/base/scrp-cjk.lua
@@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['scrp-cjk'] = {
license = "see context related readme files"
}
+-- We can speed this up by preallocating nodes and copying them but the
+-- gain is not that large.
+
local utfchar = utf.char
local has_attribute = node.has_attribute
diff --git a/tex/context/base/scrp-ini.lua b/tex/context/base/scrp-ini.lua
index e55dc0780..9b0e9fc21 100644
--- a/tex/context/base/scrp-ini.lua
+++ b/tex/context/base/scrp-ini.lua
@@ -47,142 +47,152 @@ local hash = scripts.hash
local handlers = allocate()
scripts.handlers = handlers
-storage.register("scripts/hash", hash, "scripts.hash")
-
-if not next(hash) then -- this might move to char-def
-
- hash = { -- no local
- --
- -- half width opening parenthesis
- [0x0028] = "half_width_open",
- [0x005B] = "half_width_open",
- [0x007B] = "half_width_open",
- [0x2018] = "half_width_open", -- ‘
- [0x201C] = "half_width_open", -- “
- --
- -- full width opening parenthesis
- --
- [0x3008] = "full_width_open", -- 〈 Left book quote
- [0x300A] = "full_width_open", -- 《 Left double book quote
- [0x300C] = "full_width_open", -- 「 left quote
- [0x300E] = "full_width_open", -- 『 left double quote
- [0x3010] = "full_width_open", -- 【 left double book quote
- [0x3014] = "full_width_open", -- 〔 left book quote
- [0x3016] = "full_width_open", --〖 left double book quote
- [0x3018] = "full_width_open", -- left tortoise bracket
- [0x301A] = "full_width_open", -- left square bracket
- [0x301D] = "full_width_open", -- reverse double prime qm
- [0xFF08] = "full_width_open", -- ( left parenthesis
- [0xFF3B] = "full_width_open", -- [ left square brackets
- [0xFF5B] = "full_width_open", -- { left curve bracket
- --
- -- half width closing parenthesis
- [0x0029] = "half_width_close",
- [0x005D] = "half_width_close",
- [0x007D] = "half_width_close",
- [0x2019] = "half_width_close", -- ’ right quote, right
- [0x201D] = "half_width_close", -- ” right double quote
- --
- -- full width closing parenthesis
- --
- [0x3009] = "full_width_close", -- 〉 book quote
- [0x300B] = "full_width_close", -- 》 double book quote
- [0x300D] = "full_width_close", -- 」 right quote, right
- [0x300F] = "full_width_close", -- 』 right double quote
- [0x3011] = "full_width_close", -- 】 right double book quote
- [0x3015] = "full_width_close", -- 〕 right book quote
- [0x3017] = "full_width_close", -- 〗 right double book quote
- [0x3019] = "full_width_close", -- right tortoise bracket
- [0x301B] = "full_width_close", -- right square bracket
- [0x301E] = "full_width_close", -- double prime qm
- [0x301F] = "full_width_close", -- low double prime qm
- [0xFF09] = "full_width_close", -- ) right parenthesis
- [0xFF3D] = "full_width_close", -- ] right square brackets
- [0xFF5D] = "full_width_close", -- } right curve brackets
-
- [0xFF62] = "half_width_open", -- left corner bracket
- [0xFF63] = "half_width_close", -- right corner bracket
- --
- -- vertical opening vertical
- --
- -- 0xFE35, 0xFE37, 0xFE39, 0xFE3B, 0xFE3D, 0xFE3F, 0xFE41, 0xFE43, 0xFE47,
- --
- -- vertical closing
- --
- -- 0xFE36, 0xFE38, 0xFE3A, 0xFE3C, 0xFE3E, 0xFE40, 0xFE42, 0xFE44, 0xFE48,
- --
- -- half width opening punctuation
- --
- -- <empty>
- --
- -- full width opening punctuation
- --
- -- 0x2236, -- ∶
- -- 0xFF0C, -- ,
- --
- -- half width closing punctuation_hw
- --
- [0x0021] = "half_width_close", -- !
- [0x002C] = "half_width_close", -- ,
- [0x002E] = "half_width_close", -- .
- [0x003A] = "half_width_close", -- :
- [0x003B] = "half_width_close", -- ;
- [0x003F] = "half_width_close", -- ?
- [0xFF61] = "half_width_close", -- hw full stop
- --
- -- full width closing punctuation
- [0x3001] = "full_width_close", -- 、
- [0x3002] = "full_width_close", -- 。
- [0xFF0C] = "full_width_close", -- ,
- [0xFF0E] = "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",
- [0x3049] = "non_starter", [0x3063] = "non_starter", [0x3083] = "non_starter", [0x3085] = "non_starter", [0x3087] = "non_starter",
- [0x308E] = "non_starter", [0x3095] = "non_starter", [0x3096] = "non_starter", [0x309B] = "non_starter", [0x309C] = "non_starter",
- [0x309D] = "non_starter", [0x309E] = "non_starter", [0x30A0] = "non_starter", [0x30A1] = "non_starter", [0x30A3] = "non_starter",
- [0x30A5] = "non_starter", [0x30A7] = "non_starter", [0x30A9] = "non_starter", [0x30C3] = "non_starter", [0x30E3] = "non_starter",
- [0x30E5] = "non_starter", [0x30E7] = "non_starter", [0x30EE] = "non_starter", [0x30F5] = "non_starter", [0x30F6] = "non_starter",
- [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31F0] = "non_starter", [0x31F1] = "non_starter",
- [0x30F2] = "non_starter", [0x30F3] = "non_starter", [0x30F4] = "non_starter", [0x31F5] = "non_starter", [0x31F6] = "non_starter",
- [0x30F7] = "non_starter", [0x30F8] = "non_starter", [0x30F9] = "non_starter", [0x31FA] = "non_starter", [0x31FB] = "non_starter",
- [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31FF] = "non_starter",
- --
- -- hyphenation
- --
- [0x2026] = "hyphen", -- … ellipsis
- [0x2014] = "hyphen", -- — hyphen
- }
-
- 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] = "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
- for i=0x01100,0x0115F do if not hash[i] then hash[i] = "jamo_initial" end end
- for i=0x01160,0x011A7 do if not hash[i] then hash[i] = "jamo_medial" end end
- for i=0x011A8,0x011FF do if not hash[i] then hash[i] = "jamo_final" end end
-
- for i=0x01200,0x0139F do hash[i] = "ethiopic_syllable" end
-
- hash[0x01361] = "ethiopic_word"
- hash[0x01362] = "ethiopic_sentence"
-
- scripts.hash = hash
+local hash = { -- we could put these presets in char-def.lua
+ --
+ -- half width opening parenthesis
+ --
+ [0x0028] = "half_width_open",
+ [0x005B] = "half_width_open",
+ [0x007B] = "half_width_open",
+ [0x2018] = "half_width_open", -- ‘
+ [0x201C] = "half_width_open", -- “
+ --
+ -- full width opening parenthesis
+ --
+ [0x3008] = "full_width_open", -- 〈 Left book quote
+ [0x300A] = "full_width_open", -- 《 Left double book quote
+ [0x300C] = "full_width_open", -- 「 left quote
+ [0x300E] = "full_width_open", -- 『 left double quote
+ [0x3010] = "full_width_open", -- 【 left double book quote
+ [0x3014] = "full_width_open", -- 〔 left book quote
+ [0x3016] = "full_width_open", --〖 left double book quote
+ [0x3018] = "full_width_open", -- left tortoise bracket
+ [0x301A] = "full_width_open", -- left square bracket
+ [0x301D] = "full_width_open", -- reverse double prime qm
+ [0xFF08] = "full_width_open", -- ( left parenthesis
+ [0xFF3B] = "full_width_open", -- [ left square brackets
+ [0xFF5B] = "full_width_open", -- { left curve bracket
+ --
+ -- half width closing parenthesis
+ --
+ [0x0029] = "half_width_close",
+ [0x005D] = "half_width_close",
+ [0x007D] = "half_width_close",
+ [0x2019] = "half_width_close", -- ’ right quote, right
+ [0x201D] = "half_width_close", -- ” right double quote
+ --
+ -- full width closing parenthesis
+ --
+ [0x3009] = "full_width_close", -- 〉 book quote
+ [0x300B] = "full_width_close", -- 》 double book quote
+ [0x300D] = "full_width_close", -- 」 right quote, right
+ [0x300F] = "full_width_close", -- 』 right double quote
+ [0x3011] = "full_width_close", -- 】 right double book quote
+ [0x3015] = "full_width_close", -- 〕 right book quote
+ [0x3017] = "full_width_close", -- 〗 right double book quote
+ [0x3019] = "full_width_close", -- right tortoise bracket
+ [0x301B] = "full_width_close", -- right square bracket
+ [0x301E] = "full_width_close", -- double prime qm
+ [0x301F] = "full_width_close", -- low double prime qm
+ [0xFF09] = "full_width_close", -- ) right parenthesis
+ [0xFF3D] = "full_width_close", -- ] right square brackets
+ [0xFF5D] = "full_width_close", -- } right curve brackets
+ --
+ [0xFF62] = "half_width_open", -- left corner bracket
+ [0xFF63] = "half_width_close", -- right corner bracket
+ --
+ -- vertical opening vertical
+ --
+ -- 0xFE35, 0xFE37, 0xFE39, 0xFE3B, 0xFE3D, 0xFE3F, 0xFE41, 0xFE43, 0xFE47,
+ --
+ -- vertical closing
+ --
+ -- 0xFE36, 0xFE38, 0xFE3A, 0xFE3C, 0xFE3E, 0xFE40, 0xFE42, 0xFE44, 0xFE48,
+ --
+ -- half width opening punctuation
+ --
+ -- <empty>
+ --
+ -- full width opening punctuation
+ --
+ -- 0x2236, -- ∶
+ -- 0xFF0C, -- ,
+ --
+ -- half width closing punctuation_hw
+ --
+ [0x0021] = "half_width_close", -- !
+ [0x002C] = "half_width_close", -- ,
+ [0x002E] = "half_width_close", -- .
+ [0x003A] = "half_width_close", -- :
+ [0x003B] = "half_width_close", -- ;
+ [0x003F] = "half_width_close", -- ?
+ [0xFF61] = "half_width_close", -- hw full stop
+ --
+ -- full width closing punctuation
+ --
+ [0x3001] = "full_width_close", -- 、
+ [0x3002] = "full_width_close", -- 。
+ [0xFF0C] = "full_width_close", -- ,
+ [0xFF0E] = "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",
+ [0x3049] = "non_starter", [0x3063] = "non_starter", [0x3083] = "non_starter", [0x3085] = "non_starter", [0x3087] = "non_starter",
+ [0x308E] = "non_starter", [0x3095] = "non_starter", [0x3096] = "non_starter", [0x309B] = "non_starter", [0x309C] = "non_starter",
+ [0x309D] = "non_starter", [0x309E] = "non_starter", [0x30A0] = "non_starter", [0x30A1] = "non_starter", [0x30A3] = "non_starter",
+ [0x30A5] = "non_starter", [0x30A7] = "non_starter", [0x30A9] = "non_starter", [0x30C3] = "non_starter", [0x30E3] = "non_starter",
+ [0x30E5] = "non_starter", [0x30E7] = "non_starter", [0x30EE] = "non_starter", [0x30F5] = "non_starter", [0x30F6] = "non_starter",
+ [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31F0] = "non_starter", [0x31F1] = "non_starter",
+ [0x30F2] = "non_starter", [0x30F3] = "non_starter", [0x30F4] = "non_starter", [0x31F5] = "non_starter", [0x31F6] = "non_starter",
+ [0x30F7] = "non_starter", [0x30F8] = "non_starter", [0x30F9] = "non_starter", [0x31FA] = "non_starter", [0x31FB] = "non_starter",
+ [0x30FC] = "non_starter", [0x30FD] = "non_starter", [0x30FE] = "non_starter", [0x31FF] = "non_starter",
+ --
+ -- hyphenation
+ --
+ [0x2026] = "hyphen", -- … ellipsis
+ [0x2014] = "hyphen", -- — hyphen
+ --
+ [0x1361] = "ethiopic_word",
+ [0x1362] = "ethiopic_sentence",
+ --
+}
+local function provide(t,k)
+ local v
+ if not tonumber(k) then v = false
+ elseif (k >= 0x03040 and k <= 0x030FF)
+ or (k >= 0x031F0 and k <= 0x031FF)
+ or (k >= 0x032D0 and k <= 0x032FE)
+ or (k >= 0x0FF00 and k <= 0x0FFEF) then v = "katakana"
+ elseif (k >= 0x03400 and k <= 0x04DFF)
+ or (k >= 0x04E00 and k <= 0x09FFF)
+ or (k >= 0x0F900 and k <= 0x0FAFF)
+ or (k >= 0x20000 and k <= 0x2A6DF)
+ or (k >= 0x2F800 and k <= 0x2FA1F) then v = "chinese"
+ elseif (k >= 0x0AC00 and k <= 0x0D7A3) then v = "korean"
+ elseif (k >= 0x01100 and k <= 0x0115F) then v = "jamo_initial"
+ elseif (k >= 0x01160 and k <= 0x011A7) then v = "jamo_medial"
+ elseif (k >= 0x011A8 and k <= 0x011FF) then v = "jamo_final"
+ elseif (k >= 0x01200 and k <= 0x0139F) then v = "ethiopic_syllable"
+ else v = false
+ end
+ t[k] = v
+ return v
end
+table.setmetatableindex(hash,provide)
+
+scripts.hash = hash
+
local numbertodataset = allocate()
local numbertohandler = allocate()
diff --git a/tex/context/base/sort-ini.lua b/tex/context/base/sort-ini.lua
index 8640ba825..a6181f5e4 100644
--- a/tex/context/base/sort-ini.lua
+++ b/tex/context/base/sort-ini.lua
@@ -527,7 +527,7 @@ local function numify(s)
return utfchar(s)
end
-function sorters.strip(str) -- todo: only letters and such utf.gsub("([^%w%d])","")
+function sorters.strip(str) -- todo: only letters and such
if str then
str = gsub(str,"\\[\"\'~^`]*","") -- \"e
str = gsub(str,"\\%S*","") -- the rest
diff --git a/tex/context/base/sort-lan.lua b/tex/context/base/sort-lan.lua
index 6a0cb8eab..d2fa276d7 100644
--- a/tex/context/base/sort-lan.lua
+++ b/tex/context/base/sort-lan.lua
@@ -3,9 +3,13 @@ if not modules then modules = { } end modules ['sort-lan'] = {
comment = "companion to sort-lan.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+ license = "see context related readme files",
+ dataonly = true,
}
+-- todo: look into uts#10 (2012) ... some experiments ... something
+-- to finish in winter.
+
-- Many vectors were supplied by Wolfgang Schuster and Philipp
-- Gesang. However this is a quite adapted and reformatted variant
-- so it needs some checking. Other users provides tables and
@@ -86,8 +90,20 @@ definitions['Duden'] = {
replacements = { { "ß", 's' } },
}
-definitions['de'] = { parent = 'default' } -- new german
+-- definitions['de'] = { parent = 'default' } -- new german
+
+definitions['de'] = {
+ parent = 'default',
+ replacements = {
+ { "ä", 'ae' }, { "Ä", 'Ae' },
+ { "ö", 'oe' }, { "Ö", 'Oe' },
+ { "ü", 'ue' }, { "Ü", 'Ue' },
+ { "ß", 's' },
+ },
+}
+
definitions['deo'] = { parent = 'de' } -- old german
+
definitions['de-DE'] = { parent = 'de' } -- german - Germany
definitions['de-CH'] = { parent = 'de' } -- german - Swiss
diff --git a/tex/context/base/spac-ali.lua b/tex/context/base/spac-ali.lua
index effd26fe4..998df3aa6 100644
--- a/tex/context/base/spac-ali.lua
+++ b/tex/context/base/spac-ali.lua
@@ -20,7 +20,7 @@ local unset_attribute = node.unset_attribute
local slide_nodes = node.slide
local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here
-local link_nodes = nodes.link
+local concat_nodes = nodes.concat
local nodecodes = nodes.nodecodes
local listcodes = nodes.listcodes
@@ -77,12 +77,12 @@ local function handler(head,leftpage,realpageno)
action = leftpage and 2 or 1
end
if action == 1 then
- current.list = hpack_nodes(link_nodes(current.list,new_stretch(3)),current.width,"exactly")
+ current.list = hpack_nodes(concat_nodes{current.list,new_stretch(3)},current.width,"exactly")
if trace_realign then
report_realign("flush left: align %s, page %s, realpage %s",align,pageno,realpageno)
end
elseif action == 2 then
- current.list = hpack_nodes(link_nodes(new_stretch(3),current.list),current.width,"exactly")
+ current.list = hpack_nodes(concat_nodes{new_stretch(3),current.list},current.width,"exactly")
if trace_realign then
report_realign("flush right: align %s, page %s, realpage %s",align,pageno,realpageno)
end
diff --git a/tex/context/base/spac-ali.mkiv b/tex/context/base/spac-ali.mkiv
index 57806b6f2..100e3ab82 100644
--- a/tex/context/base/spac-ali.mkiv
+++ b/tex/context/base/spac-ali.mkiv
@@ -268,7 +268,7 @@
\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
-% \!!plus ... slower than inline
+% \s!plus ... slower than inline
\unexpanded\def\spac_align_set_horizontal_none % should also relax \updateraggedskips
{\raggedstatus\zerocount
@@ -285,8 +285,8 @@
{\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
+ \leftskip \plusone\leftskip \s!plus\spac_align_set_raggedness_left
+ \rightskip \plusone\rightskip\s!plus\zeropoint
\spaceskip \v_spac_align_space_amount
\xspaceskip \v_spac_align_space_amount_x
\parfillskip\s_zero_plus_zero
@@ -297,8 +297,8 @@
{\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
+ \leftskip \plusone\leftskip \s!plus\spac_align_set_raggedness_middle
+ \rightskip \plusone\rightskip\s!plus\spac_align_set_raggedness_middle
\spaceskip \v_spac_align_space_amount
\xspaceskip \v_spac_align_space_amount_x
\parfillskip\s_zero_plus_zero
@@ -309,8 +309,8 @@
{\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
+ \leftskip \plusone\leftskip \s!plus\zeropoint
+ \rightskip \plusone\rightskip\s!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
@@ -320,8 +320,8 @@
\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
+ \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount
+ \rightskip \plusone\rightskip\s!plus\zeropoint
\spaceskip \v_spac_align_space_amount
\xspaceskip \v_spac_align_space_amount_x
\parfillskip\s_zero_plus_zero
@@ -331,8 +331,8 @@
\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
+ \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount
+ \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount
\spaceskip \v_spac_align_space_amount
\xspaceskip \v_spac_align_space_amount_x
\parfillskip\s_zero_plus_zero
@@ -342,8 +342,8 @@
\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
+ \leftskip \plusone\leftskip \s!plus\zeropoint
+ \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount
\spaceskip \v_spac_align_space_amount
\xspaceskip \v_spac_align_space_amount_x
\parfillskip\s_zero_plus_zero
@@ -354,8 +354,8 @@
{\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
+ \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount_half
+ \rightskip \plusone\rightskip\s!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
@@ -365,11 +365,11 @@
\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
+ \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax
+ \rightskip \plusone\rightskip\s!plus\v_spac_align_fill_amount_negative\relax
\spaceskip \zeropoint\relax
\xspaceskip \zeropoint\relax
- \parfillskip\zeropoint\!!plus\v_spac_align_fill_amount_double\relax
+ \parfillskip\zeropoint\s!plus\v_spac_align_fill_amount_double\relax
\parindent \zeropoint
\relax}
@@ -377,8 +377,8 @@
{\tttf % brrr
\raggedstatus\plusthree
\attribute\alignstateattribute\plusthree
- \leftskip \plusone\leftskip \!!plus\zeropoint\relax
- \rightskip \plusone\rightskip\!!plus\spac_align_set_raggedness_right\relax
+ \leftskip \plusone\leftskip \s!plus\zeropoint\relax
+ \rightskip \plusone\rightskip\s!plus\spac_align_set_raggedness_right\relax
\spaceskip \zeropoint\relax
\xspaceskip \zeropoint\relax
\parfillskip\s_zero_plus_zero
@@ -386,7 +386,7 @@
\relax}
\unexpanded\def\spac_align_set_horizontal_extra
- {\xspaceskip\zeropoint\!!plus\v_spac_align_fill_amount_space\relax}
+ {\xspaceskip\zeropoint\s!plus\v_spac_align_fill_amount_space\relax}
\def\spac_align_flush_horizontal
{\ifcase\c_spac_align_state_horizontal
@@ -651,6 +651,10 @@
\let\forgetragged \spac_align_set_horizontal_none
+\appendtoks
+ \spac_align_set_horizontal_none
+\to \everyforgetall
+
% Box commands.
\unexpanded\def\ibox#1#2#3%
@@ -735,11 +739,11 @@
\def\dosetraggedskips#1#2#3#4#5#6#7%
{\raggedstatus #1\relax
- \leftskip 1\leftskip \!!plus#2\relax
- \rightskip 1\rightskip\!!plus#3\relax
+ \leftskip 1\leftskip \s!plus#2\relax
+ \rightskip 1\rightskip\s!plus#3\relax
\spaceskip #4\relax
\xspaceskip #5\relax
- \parfillskip \zeropoint\!!plus#6\relax
+ \parfillskip \zeropoint\s!plus#6\relax
\parindent #7\relax
\attribute\alignstateattribute\ifcase\raggedstatus\attributeunsetvalue\else\raggedstatus\fi}
diff --git a/tex/context/base/spac-cha.mkiv b/tex/context/base/spac-cha.mkiv
new file mode 100644
index 000000000..a07c8f198
--- /dev/null
+++ b/tex/context/base/spac-cha.mkiv
@@ -0,0 +1,191 @@
+%D \module
+%D [ file=spac-cha, % was supp-ali,
+%D version=2012.06.08, % 2000.04.17,
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Character Alignment,
+%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 Yet undocumented but nevertheless used.
+
+% 0 = centered
+% 1 = left in before
+% 2 = right in before
+% 3 = left in after
+% 4 = right in after
+
+\unprotect
+
+% \starttabulate[|cg{.}|cg{,}|cg{,}|]
+% \NC period \NC comma \NC comma \NC\NR
+% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR
+% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR
+% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
+% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
+% \NG 10\\ \NG 10\\ \NG 0,00 \NC\NR
+% \NG 10 \NG 10 \NG 0,00 \NC\NR
+% \NG 10 \NG 10 \NG 0,00 \NC\NR
+% \stoptabulate
+
+% We gain not much by luafication and actually make things worse.
+
+\chardef\characteralignmentmode\plusfour
+\chardef\characteralignmentslot\plusone
+
+\let\afterassignwidth \!!zeropoint
+\let\beforeassignwidth\!!zeropoint
+
+\def\alignmentcharacter{.}
+
+\newdimen\d_supp_charalign_width
+\newtoks \t_supp_charalign_list
+
+\let\alignmentclass\s!default % can be used to handle multiple mixed ones
+
+\installcorenamespace{characteralign}
+
+\unexpanded\def\supp_charalign_push
+ {\ifcsname\??characteralign\alignmentclass\endcsname\else
+ \normalexpanded{\global\t_supp_charalign_list{\the\t_supp_charalign_list\supp_charalign_do{\alignmentclass}}}%
+ \fi
+ \setxvalue{\??characteralign\alignmentclass}{\supp_charalign_do
+ {\afterassignwidth}{\beforeassignwidth}{\alignmentcharacter}}}
+
+\unexpanded\def\supp_charalign_pop_do#1#2#3%
+ {\def\afterassignwidth {#1}%
+ \def\beforeassignwidth {#2}%
+ \def\alignmentcharacter{#3}}
+
+\unexpanded\def\supp_charalign_pop
+ {\let\supp_charalign_do\supp_charalign_pop_do
+ \executeifdefined{\??characteralign\alignmentclass}\donothing}
+
+\unexpanded\def\supp_charalign_reset_do#1%
+ {\global\letbeundefined{\??characteralign#1}} % global !
+
+\unexpanded\def\resetcharacteralign
+ {\let\supp_charalign_do\supp_charalign_reset_do
+ \the\t_supp_charalign_list
+ \global\t_supp_charalign_list\emptytoks}
+
+\unexpanded\def\supp_charalign_firstpass_one#1#2%
+ {\supp_charalign_pop
+ \let\\\empty
+ \setbox\scratchbox\hbox{#1}%
+ \d_supp_charalign_width\wd\scratchbox
+ \setbox\scratchbox\emptyhbox
+ \supp_charalign_check#2#1\relax\relax
+ \scratchdimen-\wd\scratchbox
+ \setbox\scratchbox\hbox{\ignorespaces#2\unskip}%
+ \advance\scratchdimen \wd\scratchbox
+ \ifdim\scratchdimen>\beforeassignwidth\relax
+ \edef\beforeassignwidth{\the\scratchdimen}%
+ \fi
+ \ifdim\scratchdimen=\zeropoint
+ \setbox\scratchbox\hbox{\ignorespaces#2\unskip}%
+ \scratchdimen\wd\scratchbox
+ \ifcase\characteralignmentmode
+ % do nothing
+ \else\ifnum\characteralignmentmode<\plusthree
+ \advance\scratchdimen\d_supp_charalign_width\relax
+ \ifdim\scratchdimen>\beforeassignwidth\relax
+ \edef\beforeassignwidth{\the\scratchdimen}%
+ \fi
+ \else
+ \ifdim\scratchdimen>\afterassignwidth\relax
+ \edef\afterassignwidth{\the\scratchdimen}%
+ \fi
+ \fi\fi
+ \fi
+ \supp_charalign_push}
+
+\unexpanded\def\supp_charalign_firstpass_two#1#2#3%
+ {\ifx#2\relax
+ \setbox\scratchbox\hbox{\ignorespaces#1\unskip}%
+ \ifdim\wd\scratchbox>\afterassignwidth
+ \edef\afterassignwidth{\the\wd\scratchbox}%
+ \fi
+ \else
+ \supp_charalign_check#2#3\relax\relax
+ \fi}
+
+\unexpanded\def\supp_charalign_secondpass_one#1#2%
+ {\supp_charalign_pop
+ \let\\\empty % beware, no grouping
+ \setbox\scratchbox\hbox{#1}%
+ \d_supp_charalign_width\wd\scratchbox
+ \setbox\scratchbox\emptyhbox
+ % new 12,34 vs 10\\ where 10 aligns on 12 if #1 = ,
+ \ifcase\characteralignmentslot
+ \supp_charalign_check#2#1\relax\relax
+ \scratchdimen\wd\scratchbox
+ \setbox\scratchbox\hbox{\ignorespaces##1\unskip}%
+ \else
+ \def\\{#1}%
+ \normalexpanded{\supp_charalign_check#2#1\relax\relax}%
+ \scratchdimen\wd\scratchbox
+ \setbox\scratchbox\hbox{\def\\{\hphantom{#1}}\ignorespaces#2\unskip}%
+ \fi
+ \noindent
+ \ifdim\scratchdimen=\wd\scratchbox
+ \ifcase\characteralignmentmode
+ \box\scratchbox
+ \else
+ \hbox
+ {\dontcomplain
+ \hbox to \beforeassignwidth
+ {\ifcase\characteralignmentmode\or
+ \box\scratchbox\hss
+ \or
+ \hss\box\scratchbox\hskip\d_supp_charalign_width
+ \or
+ \hss\rlap{\box\scratchbox}%
+ \or
+ \hss\rlap{\hbox to \afterassignwidth{\hss\box\scratchbox}}%
+ \fi}%
+ \hskip\afterassignwidth}%
+ \fi
+ \else
+ \hbox
+ {\hbox to \beforeassignwidth
+ {\hss\box\scratchbox\hskip-\scratchdimen}%
+ \hskip\afterassignwidth}%
+ \fi}
+
+\unexpanded\def\supp_charalign_secondpass_two#1#2#3%
+ {\ifx#2\relax
+ \setbox\scratchbox\hbox{\ignorespaces#1\unskip}%
+ \else
+ \supp_charalign_check#2#3\relax\relax
+ \fi}
+
+\unexpanded\def\supp_charalign_firstpass#1%
+ {\unexpanded\def\checkalignment ##1{\supp_charalign_firstpass_one{#1}{##1}}%
+ \unexpanded\def\supp_charalign_check##1#1##2##3\relax{\supp_charalign_firstpass_two{##1}{##2}{##3}}}
+
+\unexpanded\def\supp_charalign_secondpass#1%
+ {\unexpanded\def\checkalignment ##1{\supp_charalign_secondpass_one{#1}{##1}}%
+ \unexpanded\def\supp_charalign_check##1#1##2##3\relax{\supp_charalign_secondpass_two{##1}{##2}{##3}}}
+
+\unexpanded\def\setfirstpasscharacteralign
+ {\supp_charalign_pop
+ \normalexpanded{\supp_charalign_firstpass{\alignmentcharacter}}}
+
+\unexpanded\def\setsecondpasscharacteralign
+ {\supp_charalign_pop
+ \normalexpanded{\supp_charalign_secondpass{\alignmentcharacter}}}
+
+\unexpanded\def\startcharacteralign#1\stopcharacteralign
+ {\bgroup
+ \setfirstpasscharacteralign #1%
+ \setsecondpasscharacteralign#1%
+ \egroup}
+
+\let\stopcharacteralign\relax
+
+\protect \endinput
diff --git a/tex/context/base/spac-def.mkiv b/tex/context/base/spac-def.mkiv
index 4cd7b1d1c..312483cfa 100644
--- a/tex/context/base/spac-def.mkiv
+++ b/tex/context/base/spac-def.mkiv
@@ -13,80 +13,45 @@
\writestatus{loading}{ConTeXt Spacing Macros / Definitions}
-% todo: move resetters to other modules
+% Ideally these definitions should be moved to where they first appear and
+% this will happen at some point.
\unprotect
-\unexpanded\def\forgeteverypar
- {\everypar{\the\neverypar}}
-
-% worth trying:
-%
-% \unexpanded\def\forgeteverypar
-% {\everypar\neverypar}
-
-\unexpanded\def\forgetparskip
- {\s_spac_whitespace_parskip\zeropoint
- \parskip\zeropoint
- \let\v_spac_whitespace_current\v!none}
-
-\unexpanded\def\forgetbothskips
- {\leftskip\zeropoint
- \rightskip\zeropoint
- \relax}
-
-\unexpanded\def\forgethorizontalstretch
- {\emergencystretch\zeropoint}
-
-\unexpanded\def\forgetverticalstretch
- {\spacing\plusone}
-
-\newif\ifforgotten % rather good signal for inner
-
-% 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 \forgetverticalstretch \to \everybodyfont
-\appendtoks \presetnormallineheight \to \everybodyfont
-\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\normalpar \to \everybeforepagebody % see \fillinline (was endgraf)
-\appendtoks \synchronizespacecodes \to \everydefinedfont % not needed, frozen factors
-
-\setupwhitespace
- [\v!none]
+% maybe \everysynchronizeglobalspacing
+% maybe \everysynchronizelocalspacing
-\indenting
- [\v!never]
+\appendtoks
+ \forgetverticalstretch
+ \presetnormallineheight
+ \setnormalbaselines % check if redundant (\forgetverticalstretch does it too)
+ \setstrut % check if redundant (\forgetverticalstretch does it too)
+ \settopskip % factors set in \forgetverticalstretch
+ \setmaxdepth % factors set in \forgetverticalstretch
+ \synchronizeindenting
+ \synchronizeblank
+ \synchronizewhitespace
+ \synchronizespacecodes % not needed, frozen factors
+ \setrelativeinterlinespace
+\to \everybodyfont
-\setupindenting
- [\v!none]
+% why exception
-\setupblank
- [\v!big] % alternatively [\v!standard]
+\appendtoks
+ \updateraggedskips % under test
+\to \everyfontswitch
+
+% maybe more
+
+\prependtoks
+ \let\par\normalpar
+\to \everybeforepagebody % see \fillinline (was endgraf)
-\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]
+% needs checking:
+
+\appendtoks
+ \synchronizespacecodes
+\to \everydefinedfont % not needed, frozen factors
\setupinterlinespace
[\c!minheight=\zeropoint, % only special purpose
@@ -97,14 +62,11 @@
\c!bottom=0.4,
\c!distance=\onepoint,
\c!line=2.8\exheight,
- \c!stretch=\zerocount]
+ \c!stretch=\zerocount,
+ \c!shrink=\zerocount]
-\setupnarrower
- [\c!before=\endgraf,
- \c!after=\endgraf,
- \c!left=1.5\emwidth,
- \c!right=1.5\emwidth,
- \c!middle=1.5\emwidth]
+\setupblank
+ [\v!big]
\setuptolerance
[\v!horizontal,\v!verystrict]
@@ -119,4 +81,10 @@
\setupspacing
[\v!packed]
+\indenting
+ [\v!never]
+
+\setupindenting
+ [\v!none]
+
\protect \endinput
diff --git a/tex/context/base/spac-grd.mkiv b/tex/context/base/spac-grd.mkiv
index 487521f6c..7b3ee6d6c 100644
--- a/tex/context/base/spac-grd.mkiv
+++ b/tex/context/base/spac-grd.mkiv
@@ -11,41 +11,42 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This module will be merged intio spac-ver.mkiv.
+%D This module will be merged into spac-ver.mkiv.
\writestatus{loading}{ConTeXt Spacing Macros / Grid Snapping}
-% buff-ver.mkiv: halfline spacing
-% strc-mat.mkiv: configure math grid (new code needed)
-% page-one.mkiv: to be checked
-% page-mul.mkiv: to be checked and redone
-% page-sid.mkiv: to be checked
-% page-set.mkiv: to be checked
-% strc-not.mkiv: to be checked
-% strc-ren.mkiv: to be checked
-% strc-flt.mkiv: to be checked (captions, probably top/bottom)
-% core-mis.mkiv: to be checked (placement, probbaly harmless)
-
\unprotect
-%D Helpers:
+%D A rather crappy macro that we need to avoid and as such it will probably
+%D disappear:
+
+\installcorenamespace{lastnodepusher}
\let\poplastnode\relax
-\def\pushlastnode
- {\ifdim\lastskip=\zeropoint
- \ifnum\lastpenalty=\zerocount
- \ifnum\lastkern=\zerocount
- \let\poplastnode\relax
- \else
- \edef\poplastnode{\kern\the\lastkern\relax}\kern-\lastkern % untested
- \fi
+\unexpanded\def\pushlastnode
+ {\csname\??lastnodepusher
+ \ifcsname\??lastnodepusher\the\lastnodetype\endcsname
+ \the\lastnodetype
\else
- \edef\poplastnode{\penalty\the\lastpenalty\relax}\nobreak % untested
+ \s!unknown
\fi
- \else
- \edef\poplastnode{\vskip\the\lastskip\relax}\vskip-\lastskip % \removelastskip
- \fi}
+ \endcsname}
+
+\setvalue{\??lastnodepusher\number\kernnodecode}%
+ {\unexpanded\edef\poplastnode{\kern\the\lastkern\relax}%
+ \kern-\lastkern}
+
+\setvalue{\??lastnodepusher\number\gluenodecode}%
+ {\unexpanded\edef\poplastnode{\vskip\the\lastskip\relax}%
+ \vskip-\lastskip}
+
+\setvalue{\??lastnodepusher\number\penaltynodecode}%
+ {\unexpanded\edef\poplastnode{\penalty\the\lastpenalty\relax}%
+ \nobreak}
+
+\setvalue{\??lastnodepusher\s!unknown}%
+ {\let\poplastnode\relax}
%D Moved from supp-box:
@@ -133,13 +134,17 @@
% \startlinecorrection \framed{xxx} \stoplinecorrection
% \input ward \par
+% to be redone:
+
\unexpanded\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]}
\unexpanded\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]}
\def\showbaselinecorrection
{\def\dobaselinecorrection % visualization is not watertight!
{\bgroup
-\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi
+ \ifdim\prevdepth>\zeropoint
+ \kern-\prevdepth
+ \fi
\setbox\scratchbox\emptyhbox
\wd\scratchbox\hsize
\dp\scratchbox\strutdp
@@ -149,9 +154,9 @@
\egroup
\prevdepth\strutdp}%
\def\dotopbaselinecorrection
- {\hrule\!!height\d_spac_lines_correction_before}%
+ {\hrule\s!height\d_spac_lines_correction_before}%
\def\dobotbaselinecorrection
- {\hrule\!!height\d_spac_lines_correction_after}}
+ {\hrule\s!height\d_spac_lines_correction_after}}
\def\dobaselinecorrection % beware, this one is redefined / used locally elsewhere
{\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi
diff --git a/tex/context/base/spac-hor.mkiv b/tex/context/base/spac-hor.mkiv
index eeb5cadfd..d0d4660bc 100644
--- a/tex/context/base/spac-hor.mkiv
+++ b/tex/context/base/spac-hor.mkiv
@@ -34,7 +34,7 @@
\unexpanded\def\setupindenting
{\doifnextoptionalelse\spac_indentation_setup_options\spac_indentation_setup_size}
-\def\spac_indentation_setup_size
+\unexpanded\def\spac_indentation_setup_size
{\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}}
\let\synchronizeindenting\spac_indentation_setup_size
@@ -286,6 +286,17 @@
\parindent\zeropoint
\let\v_spac_indentation_current\v!none}
+\appendtoks
+ \forgetparindent
+\to \everyforgetall
+
+\unexpanded\def\forgethorizontalstretch
+ {\emergencystretch\zeropoint}
+
+\appendtoks
+ \forgethorizontalstretch
+\to \everyforgetall % needed in pagebody
+
%D Helper:
\unexpanded\def\softbreak
@@ -406,7 +417,16 @@
\appendtoks
\let~\space
\let\ \space
-\to \simplifiedcommands
+\to \everysimplifycommands
+
+\newsignal\s_spac_keep_unwanted_space
+
+\unexpanded\def\keepunwantedspaces
+ {\ifhmode
+ \ifdim\lastskip=\s_spac_keep_unwanted_space\else
+ \hskip\s_spac_keep_unwanted_space\relax
+ \fi
+ \fi}
\unexpanded\def\removeunwantedspaces
{\ifhmode
@@ -415,7 +435,12 @@
\def\spac_helpers_remove_unwantedspace
{\ifnum\lastnodetype=\gluenodecode
- \unskip \expandafter\spac_helpers_remove_unwantedspace
+ \ifdim\lastskip=\s_spac_keep_unwanted_space\relax
+ \unskip
+ \else
+ \unskip
+ \doubleexpandafter\spac_helpers_remove_unwantedspace
+ \fi
\fi}
% \startbuffer
@@ -466,14 +491,19 @@
% Bovendien definieren we enkele extra \fill's:
-\unexpanded\def\hfilll{\hskip\zeropoint\!!plus1filll\relax}
-\unexpanded\def\vfilll{\vskip\zeropoint\!!plus1filll\relax}
+\unexpanded\def\hfilll {\hskip\zeropoint\s!plus1\s!filll\relax}
+\unexpanded\def\vfilll {\vskip\zeropoint\s!plus1\s!filll\relax}
+
+%unexpanded\def\hfilneg {\hskip\zeropoint\s!plus-1\s!fil\relax}
+\unexpanded\def\hfillneg {\hskip\zeropoint\s!plus-1\s!fill\relax}
+\unexpanded\def\hfilllneg{\hskip\zeropoint\s!plus-1\s!filll\relax}
+%unexpanded\def\vfilneg {\vskip\zeropoint\s!plus-1\s!fil\relax}
+\unexpanded\def\vfillneg {\vskip\zeropoint\s!plus-1\s!fill\relax}
+\unexpanded\def\vfilllneg{\vskip\zeropoint\s!plus-1\s!filll\relax}
\unexpanded\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup}
\unexpanded\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere
-% needs a proper \definenarrower or installnarrower
-%
% maybe we should hash the analysis
\installcorenamespace{narrower}
@@ -576,9 +606,6 @@
\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}
@@ -613,6 +640,24 @@
\unexpanded\def\doadaptleftskip #1{\dosetleftskipadaption {#1}\advance\leftskip \leftskipadaption }
\unexpanded\def\doadaptrightskip#1{\dosetrightskipadaption{#1}\advance\rightskip\rightskipadaption}
+\unexpanded\def\forgetbothskips
+ {\leftskip\zeropoint
+ \rightskip\zeropoint
+ \relax}
+
+\appendtoks
+ \forgetbothskips
+\to \everyforgetall
+
+\unexpanded\def\forgetparskip
+ {\s_spac_whitespace_parskip\zeropoint
+ \parskip\zeropoint
+ \let\v_spac_whitespace_current\v!none}
+
+\appendtoks
+ \forgetparskip
+\to \everyforgetall
+
%D Tolerance (can also be set with align):
\installcorenamespace{tolerancemethods}
@@ -626,7 +671,7 @@
\installtolerancemethod \v!vertical \v!verytolerant {\def\bottomtolerance{.100}}
\installtolerancemethod \v!horizontal \v!stretch {\emergencystretch\bodyfontsize}
-\installtolerancemethod \v!horizontal \v!space {\spaceskip.5em\!!plus.25em\!!minus.25em\relax}
+\installtolerancemethod \v!horizontal \v!space {\spaceskip.5em\s!plus.25em\s!minus.25em\relax}
\installtolerancemethod \v!horizontal \v!verystrict {\tolerance 200 }
\installtolerancemethod \v!horizontal \v!strict {\tolerance1500 }
\installtolerancemethod \v!horizontal \v!tolerant {\tolerance3000 }
@@ -861,8 +906,8 @@
\def\flexiblespaceamount#1#2#3%
{#1\interwordspace
- \!!plus#2\interwordstretch
- \!!minus#3\interwordshrink}
+ \s!plus#2\interwordstretch
+ \s!minus#3\interwordshrink}
\def\fixedspaceamount#1%
{#1\interwordspace}
@@ -947,7 +992,7 @@
\mskip#1%
\else
\scratchdimen#1\hspaceamount\empty{#2}%
- \scratchskip\scratchdimen\!!plus.5\scratchdimen\!!minus.3\scratchdimen
+ \scratchskip\scratchdimen\s!plus.5\scratchdimen\s!minus.3\scratchdimen
\hskip\scratchskip
\fi
\endgroup}
@@ -956,4 +1001,68 @@
\unexpanded\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium}
\unexpanded\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big}
+%D A rather unknown one:
+
+\unexpanded\def\widened % moved from cont-new
+ {\doifnextoptionalelse\spac_widened_yes\spac_widened_nop}
+
+\def\spac_widened_yes[#1]#2{\hbox \s!spread #1{\hss#2\hss}}
+\def\spac_widened_nop #1{\hbox \s!spread \emwidth{\hss#1\hss}}
+
+\definecomplexorsimple\widened
+
+%D For the moment here (used in page-txt):
+
+\unexpanded\def\ignoredlinebreak{\unskip\space\ignorespaces}
+
+%D \macros
+%D {startignorespaces}
+%D
+%D I'll probably forget that this one exists:
+%D
+%D \starttyping
+%D \ruledhbox
+%D {\startignorespaces
+%D \def\oeps{a}
+%D \startignorespaces
+%D \def\oeps{a}
+%D \stopignorespaces
+%D \def\oeps{a}
+%D \stopignorespaces
+%D \oeps}
+%D \stoptyping
+
+\newsignal\s_spac_ignore_spaces
+\newcount \c_spac_ignore_spaces
+
+\unexpanded\def\startignorespaces
+ {\advance\c_spac_ignore_spaces\plusone
+ \ifcase\c_spac_ignore_spaces\or \ifhmode
+ \hskip\s_spac_ignore_spaces
+ \fi \fi
+ \ignorespaces}
+
+\unexpanded\def\stopignorespaces
+ {\ifcase\c_spac_ignore_spaces \or
+ \ifhmode
+ \doloop\spac_ignore_spaces_body
+ \fi
+ \fi
+ \advance\c_spac_ignore_spaces\minusone}
+
+\def\spac_ignore_spaces_body
+ {\ifdim\lastskip=\zeropoint
+ \exitloop
+ \else\ifdim\lastskip=\s_spac_ignore_spaces
+ \unskip
+ \exitloop
+ \else
+ \unskip
+ \fi\fi}
+
+%D \macros
+%D {obeyfollowingtoken}
+
+\def\obeyfollowingtoken{{}} % end \cs scanning
+
\protect \endinput
diff --git a/tex/context/base/spac-par.mkiv b/tex/context/base/spac-par.mkiv
index af032a145..6b7ed4f7d 100644
--- a/tex/context/base/spac-par.mkiv
+++ b/tex/context/base/spac-par.mkiv
@@ -203,4 +203,11 @@
\fi
\glet\flushpostponednodedata\relax}
+\unexpanded\def\doflushatpar
+ {\ifvmode
+ \expandafter\flushatnextpar
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
\protect \endinput
diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua
index 66698a49e..ace3ed8bb 100644
--- a/tex/context/base/spac-ver.lua
+++ b/tex/context/base/spac-ver.lua
@@ -42,16 +42,18 @@ local stoptiming = statistics.stoptiming
-- vertical space handler
-local trace_vbox_vspacing = false trackers.register("builders.vbox_vspacing", function(v) trace_vbox_vspacing = v end)
-local trace_page_vspacing = false trackers.register("builders.page_vspacing", function(v) trace_page_vspacing = v end)
-local trace_collect_vspacing = false trackers.register("builders.collect_vspacing", function(v) trace_collect_vspacing = v end)
-local trace_vspacing = false trackers.register("builders.vspacing", function(v) trace_vspacing = v end)
-local trace_vsnapping = false trackers.register("builders.vsnapping", function(v) trace_vsnapping = v end)
-local trace_vpacking = false trackers.register("builders.vpacking", function(v) trace_vpacking = v end)
+local trace_vbox_vspacing = false trackers.register("vspacing.vbox", function(v) trace_vbox_vspacing = v end)
+local trace_page_vspacing = false trackers.register("vspacing.page", function(v) trace_page_vspacing = v end)
+local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end)
+local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end)
+local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end)
+local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end)
+local trace_vpacking = false trackers.register("vspacing.packing", function(v) trace_vpacking = v end)
local report_vspacing = logs.reporter("vspacing","spacing")
local report_collapser = logs.reporter("vspacing","collapsing")
local report_snapper = logs.reporter("vspacing","snapping")
+local report_page_builder = logs.reporter("builders","page")
local a_skipcategory = attributes.private('skipcategory')
local a_skippenalty = attributes.private('skippenalty')
@@ -65,6 +67,7 @@ local unset_attribute = node.unset_attribute
local set_attribute = node.set_attribute
local find_node_tail = node.tail
local free_node = node.free
+local free_node_list = node.flush_list
local copy_node = node.copy
local traverse_nodes = node.traverse
local traverse_nodes_id = node.traverse_id
@@ -1216,7 +1219,6 @@ end
function vspacing.pagehandler(newhead,where)
-- local newhead = texlists.contrib_head
if newhead then
- -- starttiming(vspacing)
local newtail = find_node_tail(newhead)
local flush = false
stackhack = true -- todo: only when grid snapping once enabled
@@ -1266,7 +1268,6 @@ function vspacing.pagehandler(newhead,where)
-- texlists.contrib_head = nil
newhead = nil
end
- -- stoptiming(vspacing)
end
return newhead
end
@@ -1316,28 +1317,51 @@ function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction)
else
nodes.processors.tracer("vpack","unchanged",head,groupcode,before,after,true)
end
- stoptiming(builders)
else
head, done = actions(head,groupcode)
- stoptiming(builders)
end
+ stoptiming(builders)
end
return head, done
end
--- This one is special in the sense that it has no head
--- and we operate on the mlv. Also, we need to do the
--- vspacing last as it removes items from the mvl.
+-- This one is special in the sense that it has no head and we operate on the mlv. Also,
+-- we need to do the vspacing last as it removes items from the mvl.
local actions = nodes.tasks.actions("mvlbuilders")
+local function report(groupcode,head)
+ report_page_builder("trigger: %s",groupcode)
+ report_page_builder(" vsize : %s",points(tex.vsize))
+ report_page_builder(" pagegoal : %s",points(tex.pagegoal))
+ report_page_builder(" pagetotal: %s",points(tex.pagetotal))
+ report_page_builder(" list : %s",head and nodeidstostring(head) or "<empty>")
+end
+
function builders.buildpage_filter(groupcode)
- starttiming(builders)
- local head = texlists.contrib_head
- local head, done = actions(head,groupcode)
- texlists.contrib_head = head
- stoptiming(builders)
- return (done and head) or true
+ local head, done = texlists.contrib_head, false
+-- if head and head.next and head.next.id == hlist_code and head.next.width == 1 then
+-- report_page_builder("trigger otr calculations")
+-- free_node_list(head)
+-- head = nil
+-- end
+ if head then
+ starttiming(builders)
+ if trace_page_builder then
+ report(groupcode,head)
+ end
+ head, done = actions(head,groupcode)
+ stoptiming(builders)
+ -- -- doesn't work here (not passed on?)
+ -- tex.pagegoal = tex.vsize - tex.dimen.d_page_floats_inserted_top - tex.dimen.d_page_floats_inserted_bottom
+ texlists.contrib_head = head
+ return done and head or true
+ else
+ if trace_page_builder then
+ report(groupcode)
+ end
+ return nil, false
+ end
end
callbacks.register('vpack_filter', builders.vpack_filter, "vertical spacing etc")
diff --git a/tex/context/base/spac-ver.mkiv b/tex/context/base/spac-ver.mkiv
index 72ee80d4f..7fdf2f70f 100644
--- a/tex/context/base/spac-ver.mkiv
+++ b/tex/context/base/spac-ver.mkiv
@@ -68,8 +68,8 @@
\def\normalskipamount
{\openlineheight
\ifgridsnapping \else \ifblankflexible
- \!!plus \skipgluefactor\openlineheight
- \!!minus\skipgluefactor\openlineheight
+ \s!plus \skipgluefactor\openlineheight
+ \s!minus\skipgluefactor\openlineheight
\fi \fi
\relax}
@@ -91,15 +91,16 @@
\spac_linespacing_setup_specified_interline_space}
\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\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\m_spac_vertical_baseline_stretch_factor{\interlinespaceparameter\c!stretch }%
+ \edef\m_spac_vertical_baseline_shrink_factor {\interlinespaceparameter\c!shrink }%
% often topskip does more bad than good, so:
\ifx\topskipfactor\v!height
\let\topskipfactor\strutheightfactor
@@ -181,12 +182,12 @@
\localinterlinespacefalse}
\unexpanded\def\dosetupcheckedinterlinespace#1% often a chain
- {\edef\askedinterlinespace{#1}%
- \ifx\askedinterlinespace\empty
+ {\edef\p_spac_checked_interlinespace{#1}%
+ \ifx\p_spac_checked_interlinespace\empty
\spac_linespacing_synchronize_local
- \else\ifcsname\namedinterlinespacehash\askedinterlinespace\s!parent\endcsname % we could have a \s!check
+ \else\ifcsname\namedinterlinespacehash\p_spac_checked_interlinespace\s!parent\endcsname % we could have a \s!check
\pushmacro\currentinterlinespace
- \let\currentinterlinespace\askedinterlinespace
+ \let\currentinterlinespace\p_spac_checked_interlinespace
\spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed
\iflocalinterlinespace
\the\everysetuplocalinterlinespace
@@ -197,8 +198,8 @@
\fi
\popmacro\currentinterlinespace
\else
- \normalexpanded{\noexpand\doifassignmentelse{\askedinterlinespace}%
- \setupspecifiedinterlinespace\setuprelativeinterlinespace[\askedinterlinespace]}%
+ \normalexpanded{\noexpand\doifassignmentelse{\p_spac_checked_interlinespace}%
+ \setupspecifiedinterlinespace\setuprelativeinterlinespace[\p_spac_checked_interlinespace]}%
\iflocalinterlinespace
\the\everysetuplocalinterlinespace
\else
@@ -217,8 +218,6 @@
\let\switchtointerlinespace\setuplocalinterlinespace
-% \definecomplexorsimple\setupinterlinespace
-
%D Helpers
\newskip \s_spac_lastskip
@@ -301,7 +300,7 @@
\def\spac_helpers_vglue_indeed
{\par
\d_spac_prevdepth\prevdepth
- \hrule\!!height\zeropoint
+ \hrule\s!height\zeropoint
\nobreak
\vskip\s_spac_lastskip
\prevdepth\d_spac_prevdepth}
@@ -309,7 +308,7 @@
\def\spac_helpers_hglue_indeed
{\dontleavehmode % \leavevmode
\c_spac_spacefactor\spacefactor
- \vrule\!!width\zeropoint
+ \vrule\s!width\zeropoint
\nobreak
\hskip\s_spac_lastskip
\spacefactor\c_spac_spacefactor}
@@ -414,6 +413,10 @@
\parskip\zeropoint
\let\v_spac_whitespace_current\v!none}
+\appendtoks
+ \forgetparskip
+\to \everyforgetall
+
% \installwhitespacemethod \s!unknown {\s_spac_whitespace_parskip\commalistelement\relax}
%
% \def\spac_whitespace_setup_method#1%
@@ -422,6 +425,9 @@
\unexpanded\def\nowhitespace{\vspacing[\v!nowhite]}
\unexpanded\def\whitespace {\vspacing[\v!white]}
+\setupwhitespace
+ [\v!none]
+
% Packed:
% todo: when packed blocks blank, we need to enable forced
@@ -527,8 +533,6 @@
{\removeunwantedspaces
\egroup}
-\newdimen\d_spac_prevdepth
-
\def\spac_lines_start_correction_yes[#1]%
{\edef\m_spac_lines_around{#1}%
\spac_lines_action_around
@@ -628,6 +632,8 @@
% niet bepaald mooi. Een hele kleine waarde (0.025) voldoet,
% omdat een positieve glue eindeloos rekbaar is.
+% more of the next will become private:
+
\newdimen\strutdimen
\newdimen\lineheight
\newdimen\openlineheight
@@ -640,12 +646,14 @@
\def\strutdepthfactor {.28}
\def\baselinefactor {2.8}
-\def\baselinegluefactor {0}
+
+\let\m_spac_vertical_baseline_stretch_factor \zerocount
+\let\m_spac_vertical_baseline_shrink_factor \zerocount
\def\minimumstrutheight {\zeropoint}
\def\minimumstrutdepth {\zeropoint}
-\def\normallineheight {\baselinefactor ex}
+\def\normallineheight {\baselinefactor\exheight}
\def\minimumlinedistance {\lineskip}
\def\strutheight {\zeropoint}
@@ -688,7 +696,7 @@
\else
\systemtopskipfactor\globalbodyfontsize
\ifcase\bottomraggednessmode % ragged bottom
- \!!plus5\globalbodyfontsize
+ \s!plus5\globalbodyfontsize
\fi
\fi
%\relax
@@ -732,8 +740,8 @@
\fi
\normalbaselineskip\openlineheight
\ifgridsnapping\else
- \!!plus \baselinegluefactor\openlineheight
- \!!minus\baselinegluefactor\openlineheight
+ \s!plus \m_spac_vertical_baseline_stretch_factor\openlineheight
+ \s!minus\m_spac_vertical_baseline_shrink_factor \openlineheight
\fi
\normallineskip\minimumlinedistance\relax % \onepoint\relax
\normallineskiplimit\zeropoint\relax
@@ -750,6 +758,13 @@
\setnormalbaselines
\setstrut}
+\unexpanded\def\forgetverticalstretch % \forgetspacing
+ {\spacing\plusone}
+
+\appendtoks
+ \forgetverticalstretch
+\to \everyforgetall % needed in otr
+
%D Sometimes one needs to freeze the interlinespacing
%D
%D \starttyping
@@ -780,7 +795,7 @@
\newbox\strutbox
-\setbox\strutbox\hbox{\vrule\!!height8.5pt\!!depth3.5pt\!!width\zeropoint} % just a start
+\setbox\strutbox\hbox{\vrule\s!height8.5pt\s!depth3.5pt\s!width\zeropoint} % just a start
\def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
@@ -846,13 +861,13 @@
\unexpanded\def\charhtstrut
{\begingroup
\setcharstrut{GJY}%
- \vrule\!!width\zeropoint\!!depth\zeropoint\!!height\strutht
+ \vrule\s!width\zeropoint\s!depth\zeropoint\s!height\strutht
\endgroup}
\unexpanded\def\chardpstrut
{\begingroup
\setcharstrut{gjy}%
- \vrule\!!width\zeropoint\!!depth\strutdp\!!height\zeropoint
+ \vrule\s!width\zeropoint\s!depth\strutdp\s!height\zeropoint
\endgroup}
% because of all the callbacks in mkiv, we avoid unnecessary boxes ...
@@ -881,20 +896,22 @@
\def\spac_struts_set_hide
{\setbox\strutbox\hbox
{\vrule
- \!!width \zeropoint
- \!!height\strutht
- \!!depth \strutdp}}
+ \s!width \zeropoint
+ \s!height\strutht
+ \s!depth \strutdp}}
\def\spac_struts_set_vide
{\setbox\strutbox\hbox
- {\hbox to \zeropoint
+ {\spac_struts_vide_hbox to \zeropoint
{% \hss % new, will be option
\vrule
- \!!width \strutwidth
- \!!height\strutht
- \!!depth \strutdp
+ \s!width \strutwidth
+ \s!height\strutht
+ \s!depth \strutdp
\hss}}}
+\let\spac_struts_vide_hbox\hbox % overloaded in trac-vis.mkiv
+
%D The dimen \type {\struttotal} holds the exact size of the
%D strut; occasionally a one scaled point difference can show
%D up with the lineheight.
@@ -1245,7 +1262,6 @@
\definesystemattribute[skipcategory] [public]
\definesystemattribute[skippenalty] [public]
\definesystemattribute[skiporder] [public]
-\definesystemattribute[displaymath] [public]
\definesystemattribute[snapmethod] [public]
\definesystemattribute[snapvbox] [public]
%definesystemattribute[snapcategory] [public]
@@ -1484,7 +1500,7 @@
\ruledvbox
\fi}
-\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\testrulewidth}
+\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth}
\unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
{\setbox#1\gridboxvbox to #3 % given size
@@ -1492,10 +1508,10 @@
\resetteststrut
\offinterlineskip
\hsize#2%
- \baselinerulefalse
\ifnum\gridboxlinenomode=\plusthree
\gridboxlinenomode\ifodd\realpageno\plusone\else\plustwo\fi
\fi
+ \topskipcorrection
\gridboxvbox % calculated size
{\getrawnoflines{#3}% \getnoflines{#3}%
\scratchdimen\dimexpr#2+\lineheight\relax
@@ -1504,17 +1520,17 @@
\hskip-.5\lineheight\relax
\ifcase\gridboxlinenomode\or
\rlap
- {\hskip.2\bodyfontsize\hskip\scratchdimen
- \infofont\hbox to 1em{\hss\recurselevel}}%
+ {\hskip\dimexpr.2\bodyfontsize+\scratchdimen\relax
+ \infofont\hbox to \emwidth{\hss\recurselevel}}%
\or
\llap
- {\infofont\hbox to 1em{\hss\recurselevel}%
+ {\infofont\hbox to \emwidth{\hss\recurselevel}%
\hskip.2\bodyfontsize}%
\fi
\vrule
- \!!height \gridboxwidth
- \!!depth \gridboxwidth
- \!!width \scratchdimen
+ \s!height \gridboxwidth
+ \s!depth \gridboxwidth
+ \s!width \scratchdimen
\par}}
\vfill}}
@@ -1587,7 +1603,8 @@
\newtoks\everybeforeblankhandling
\newtoks\everyafterblankhandling
-\newconditional\someblankdone
+\newconditional\c_space_vspacing_done
+\newconditional\c_space_vspacing_fixed
\appendtoks
\s_spac_vspacing_temp\zeropoint
@@ -1595,40 +1612,41 @@
\attribute\skippenaltyattribute \attributeunsetvalue
\attribute\skiporderattribute \attributeunsetvalue
\ifgridsnapping
- \settrue\blankisfixed
+ \settrue\c_space_vspacing_fixed
\else
- \setfalse\blankisfixed
+ \setfalse\c_space_vspacing_fixed
\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
+ \ifconditional\c_space_vspacing_fixed \else
+ \s!plus \skipgluefactor\s_spac_vspacing_temp
+ \s!minus\skipgluefactor\s_spac_vspacing_temp
\fi
+ \relax
\to \everyafterblankhandling
\def\setblankcategory#1%
- {\settrue\someblankdone
+ {\settrue\c_space_vspacing_done
\attribute\skipcategoryattribute#1\relax}
\def\setblankorder#1%
{\attribute\skiporderattribute#1\relax}
\def\fixedblankskip
- {\settrue\blankisfixed}
+ {\settrue\c_space_vspacing_fixed}
\def\flexibleblankskip
- {\setfalse\blankisfixed}
+ {\setfalse\c_space_vspacing_fixed}
\def\addblankskip#1#2#3%
- {\settrue\someblankdone
+ {\settrue\c_space_vspacing_done
\advance\s_spac_vspacing_temp#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax}
\def\setblankpenalty#1%
{\flushblankhandling
- \settrue\someblankdone
+ \settrue\c_space_vspacing_done
\attribute\skipcategoryattribute \plusthree
\attribute\skippenaltyattribute #1\relax
\flushblankhandling}
@@ -1646,30 +1664,30 @@
\def\dostartblankhandling
{\begingroup
- \setfalse\someblankdone
+ \setfalse\c_space_vspacing_done
\the\everybeforeblankhandling}
\unexpanded\def\stopblankhandling
{\the\everyafterblankhandling
- \ifconditional\someblankdone
+ \ifconditional\c_space_vspacing_done
\vskip\s_spac_vspacing_temp
\fi
\endgroup}
\def\flushblankhandling
{\the\everyafterblankhandling
- \ifconditional\someblankdone
+ \ifconditional\c_space_vspacing_done
\vskip\s_spac_vspacing_temp
\fi
- \setfalse\someblankdone
+ \setfalse\c_space_vspacing_done
\the\everybeforeblankhandling}
\def\addpredefinedblankskip#1#2%
- {\settrue\someblankdone
+ {\settrue\c_space_vspacing_done
\advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax}
\def\addaskedblankskip#1#2%
- {\settrue\someblankdone
+ {\settrue\c_space_vspacing_done
\advance\s_spac_vspacing_temp#1\dimexpr#2\relax}
% The main spacer:
@@ -1696,13 +1714,13 @@
\fi\fi}
\def\spac_vspacing_yes_indeed[#1]%
- {\ifmmode\else\ctxcommand{vspacing("#1")}\fi}
+ {\ifmmode\else\par\ctxcommand{vspacing("#1")}\fi}
\def\spac_vspacing_yes_ignore[#1]%
{\ifmmode\else\par\fi}
\def\spac_vspacing_nop_indeed
- {\ifmmode\else\ctxcommand{vspacing("\currentvspacing")}\fi}
+ {\ifmmode\else\par\ctxcommand{vspacing("\currentvspacing")}\fi}
\def\spac_vspacing_nop_ignore
{\ifmmode\else\par\fi}
@@ -1730,17 +1748,6 @@
\let\synchronizevspacing\setupvspacing_nop
-% used both
-
-\unexpanded\def\inhibitblank
- {\vspacing[\v!disable]} % can be made faster
-
-\let\doinhibitblank\inhibitblank % keep this command, used in styles
-
-\let\setupblank \setupvspacing
-\let\blank \vspacing
-\let\synchronizeblank\synchronizevspacing
-
% category:4 is default
% this interface might change (into an \install, buw we will then keep this one hidden)
@@ -1790,12 +1797,27 @@
\dorecurse{10} % todo: other values < 4000
{\normalexpanded{\definevspacing[\v!samepage-\recurselevel][penalty:\the\numexpr4000+250*\recurselevel\relax]}}
+\definevspacing[\v!default] [\v!big] % todo: needs to adapt to \setupblank
+\definevspacing[\v!before] [\v!default] % but we need to avoid circular references
+\definevspacing[\v!inbetween][\v!default] % then
+\definevspacing[\v!after] [\v!before]
+
+\setupvspacing
+ [\v!big] % alternatively [\v!standard]
+
%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
+\unexpanded\def\inhibitblank
+ {\vspacing[\v!disable]} % can be made faster
+
+\let\doinhibitblank\inhibitblank % keep this command, used in styles
+
\let\defineblank \definevspacing
+\let\setupblank \setupvspacing
+\let\blank \vspacing
+\let\synchronizeblank \synchronizevspacing
\let\defineblankmethod\definevspacingamount
%D The following command is for Wolfgang. It has to be used with
@@ -1850,4 +1872,125 @@
\relax
\fi}
+%D Some preliminary code: a simple and fast hanger, for usage in
+%D macros (moved from cont-new).
+
+\installcorenamespace {hanging}
+
+\installdirectcommandhandler \??hanging {hanging}
+
+\setuphanging
+ [\c!distance=.5em]
+
+\unexpanded\def\starthanging
+ {\noindent\bgroup
+ \dowithnextboxcs\spac_hanging_finish\hbox}
+
+\def\spac_hanging_finish
+ {\setbox\nextbox\hbox
+ {\box\nextbox
+ \hskip\directhangingparameter\c!distance}%
+ \hangindent\wd\nextbox
+ \hangafter\plusone
+ \box\nextbox
+ \ignorespaces}
+
+\unexpanded\def\stophanging
+ {\endgraf
+ \egroup}
+
+\unexpanded\def\starthangaround
+ {\noindent\bgroup
+ \dowithnextboxcs\spac_hanging_around_finish\hbox}
+
+\def\spac_hanging_around_finish
+ {\ifdim\nextboxht>\strutht
+ \setbox\nextbox\tbox
+ {\box\nextbox}%
+ \fi
+ \setbox\nextbox\hbox
+ {\box\nextbox
+ \hskip\directhangingparameter\c!distance}%
+ \getboxheight\scratchdimen\of\box\nextbox
+ \getnoflines\scratchdimen
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \hangindent\wd\nextbox
+ \hangafter-\noflines
+ \llap{\box\nextbox}%
+ \ignorespaces}
+
+\unexpanded\def\stophangaround
+ {\endgraf
+ \egroup}
+
+%D \macros
+%D {startfixed}
+%D
+%D \starttyping
+%D \startitemize
+%D \startitem \externalfigure[cow][height=1cm] \stopitem
+%D \startitem \externalfigure[cow][height=1cm] \stopitem
+%D
+%D \startitem \startfixed \externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[high]\externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[low] \externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D \startitem \startfixed[lohi]\externalfigure[cow][height=1cm]\stopfixed \stopitem
+%D
+%D \startitem test \par \startfixed \externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[high]\externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[low] \externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \startitem test \par \startfixed[lohi]\externalfigure[koe][height=1cm]\stopfixed \stopitem
+%D \stopitemize
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace{fixedalternatives}
+
+\unexpanded\def\startfixed
+ {\bgroup
+ \dosingleempty\typo_fixed_start}
+
+\def\typo_fixed_start
+ {\ifhmode
+ \expandafter\typo_fixed_start_h
+ \else
+ \expandafter\typo_fixed_start_v
+ \fi}
+
+\def\typo_fixed_start_h[#1]%
+ {\let\stopfixed\typo_fixed_stop_h
+ \dowithnextbox{\typo_fixed_finish{#1}}%
+ \vbox\bgroup
+ %ignorespaces
+ \setlocalhsize}
+
+\unexpanded\def\typo_fixed_stop_h
+ {%removeunwantedspaces
+ \egroup
+ \egroup}
+
+\def\typo_fixed_start_v[#1]%
+ {\let\stopfixed\typo_fixed_stop_v
+ \startbaselinecorrection}
+
+\unexpanded\def\typo_fixed_stop_v
+ {\stopbaselinecorrection
+ \egroup}
+
+\letvalue{\??fixedalternatives \v!high}\bbox
+\letvalue{\??fixedalternatives \v!low}\tbox
+\letvalue{\??fixedalternatives \v!middle}\vcenter
+\letvalue{\??fixedalternatives \v!lohi}\vcenter
+\letvalue{\??fixedalternatives\s!unknown}\tbox
+\letvalue{\??fixedalternatives\s!default}\tbox
+
+\unexpanded\def\typo_fixed_finish#1%
+ {\expandcheckedcsname\??fixedalternatives{#1}\s!default{\box\nextbox}}
+
+% %D Forgotten already:
+%
+% \def\shapefill{\vskip\zeropoint\s!plus\lineheight\s!minus\lineheight\relax}
+
\protect \endinput
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index 8d2ac5857..fedf9a077 100644
--- a/tex/context/base/status-files.pdf
+++ b/tex/context/base/status-files.pdf
Binary files differ
diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf
index 0d58d1b16..acc1ebe16 100644
--- a/tex/context/base/status-lua.pdf
+++ b/tex/context/base/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/status-mkiv.lua b/tex/context/base/status-mkiv.lua
index d7ab099a6..f8c6c692b 100644
--- a/tex/context/base/status-mkiv.lua
+++ b/tex/context/base/status-mkiv.lua
@@ -1,1515 +1,5873 @@
--- 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 = "okay",
- comment = "will grow",
- },
- {
- 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 = "okay",
- comment = "maybe singular setup"
- },
- {
- 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 = "okay",
- },
- {
- filename = "chem-str",
- marktype = "mkiv",
- status = "okay",
- },
- {
- 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",
- },
- }
+ todo = {
+ category = "lua",
+ filename = "core-run",
+ status = "idea",
+ },
+ main = {
+ {
+ category = "mkiv",
+ filename = "context",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "lus",
+ comment = "stub file for context",
+ filename = "context",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "metatex",
+ loading = "parent",
+ status = "pending",
+ },
+ {
+ category = "lus",
+ comment = "stub file for metatex",
+ filename = "metatex",
+ loading = "parent",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-cs",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-de",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-en",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-fr",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-gb",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-it",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-nl",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-pe",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-ro",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "maybe more delayed loading",
+ filename = "metafun",
+ loading = "parent",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "we keep this around for historic reasons",
+ filename = "ppchtex",
+ loading = "never",
+ status = "okay",
+ },
+ },
+ core = {
+ {
+ category = "mkiv",
+ filename = "syst-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "norm-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "syst-pln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "syst-mes",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "luat-cod",
+ loading = "luat-cod",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (3)",
+ filename = "luat-bas",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (3)",
+ filename = "luat-lib",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "forward dependency",
+ filename = "catc-act",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-sym",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "catc-xml",
+ loading = "module",
+ status = "okay",
+ comment = "only needed for mkii xml parser",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "cldf-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "syst-aux",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "syst-lua",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "syst-con",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "syst-fnt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe combine (1)",
+ filename = "syst-rtp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe combine (2)",
+ filename = "file-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe combine (2)",
+ filename = "file-res",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "file-lib",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "supp-dir",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "char-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "char-utf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "forward dependency",
+ filename = "char-act",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-sys",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-aux",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-chk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "mult-dim",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cldf-int",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "luat-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe this becomes a runtime module",
+ filename = "toks-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code might move from here",
+ filename = "core-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might need more redoing",
+ filename = "core-env",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "in due time more might move to here",
+ filename = "layo-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe this becomes a runtime module",
+ filename = "node-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe use context.generics/context.sprint here",
+ filename = "cldf-bas",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might need more redoing",
+ filename = "node-fin",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs integration and configuration",
+ filename = "node-mig",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-bld",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "node-pag",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "back-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-col",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-lay",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-neg",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "attr-eff",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs more usage",
+ filename = "trac-tex",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "trac-deb",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "trac-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "supp-box",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "supp-ran",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be moved to the math-* modules",
+ filename = "supp-mat",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will grow",
+ filename = "typo-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "file-syn",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "file-mod",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "core-con",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-fil",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-nop",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-yes",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "regi-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "enco-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "hand-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "namespace should be languages",
+ filename = "lang-lab",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "unic-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "core-uti",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe rename to core-two",
+ filename = "core-two",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "core-dat",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-ext",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-grp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "node-bck",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-cut",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-mis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-url",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-frq",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-frd",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lang-wrd",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "might need more redoing",
+ filename = "file-job",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "sort-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "pack-mis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-rul",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "endpar experimental code",
+ filename = "pack-mrl",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "pack-bck",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-fen",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lxml-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "lxml-sor",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "typo-prc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-tag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this module migh tgo away when code has been moved",
+ filename = "strc-doc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "still some rough edges",
+ filename = "strc-num",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-mar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-sbe",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvI",
+ filename = "strc-lst",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "some of the local current and synchronization macros will be renamed",
+ filename = "strc-sec",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "(support for) setups might get improved",
+ filename = "strc-ren",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this module might go away",
+ filename = "strc-xml",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "some more low level names might change",
+ filename = "strc-ref",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "use setups for rendering",
+ filename = "strc-reg",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-lev",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe some tuning is needed / will happen",
+ filename = "spac-ali",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "probably needs some more work",
+ filename = "spac-hor",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe some changes will happen",
+ filename = "spac-ver",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "could be improved if needed",
+ filename = "spac-lin",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this needs to be checked occasionally",
+ filename = "spac-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-par",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-def",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "needs thinking and redoing",
+ filename = "spac-grd",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "in transition",
+ filename = "anch-pos",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe change locationattribute names",
+ filename = "scrn-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-ref",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will change when we have objects at lua end",
+ filename = "pack-obj",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-itm",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe more common counter code here and setups need to be improved",
+ filename = "strc-con",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "strc-des",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "(interactive) coupling is not yet working",
+ filename = "strc-enu",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-ind",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs to be adapted when strc-con/des/enu changes",
+ filename = "strc-lab",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-syn",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "a funny mix",
+ filename = "core-sys",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-var",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "page-otr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code might end up elsewhere",
+ filename = "page-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "dealing with insertions might change",
+ filename = "page-ins",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-fac",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "otr commands will be redone",
+ filename = "page-brk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "helpers for columns",
+ filename = "page-col",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "room for improvement and extension",
+ filename = "page-inf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-grd",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be extended when columns are redone",
+ filename = "page-flt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-bck",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-not",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "can probably be improved",
+ filename = "page-one",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-lay",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "page-box",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "a few things left",
+ filename = "page-txt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-sid",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "in due time we need a further cleanup",
+ filename = "strc-flt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-pst",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "might be extended",
+ filename = "page-mbk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be reimplemented",
+ filename = "page-mul",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "work in progress",
+ filename = "page-mix",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "will be reimplemented",
+ filename = "page-set",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-lyr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-pos",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "page-mak",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will probably be overhauled some day",
+ filename = "page-lin",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might get extended",
+ filename = "page-par",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-mar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-itm",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "check other modules for buffer usage",
+ filename = "buff-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "check obsolete processbuffer",
+ filename = "buff-ver",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "experimental code",
+ filename = "buff-par",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-tex",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-mp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-lua",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-xml",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-parsed-xml",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-default",
+ loading = "indirect",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-escaped",
+ loading = "indirect",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "buff-imp-nested",
+ loading = "indirect",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-blk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-imp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe some extensions and delayed loading, needs checking",
+ filename = "page-sel",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-com",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "functionality needs checking",
+ filename = "scrn-wid",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-but",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-bar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "strc-bkm",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "somewhat weird",
+ filename = "tabl-com",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "unchecked",
+ filename = "tabl-pln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "tabl-tab",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ comment = "can probably be improved (names and such)",
+ filename = "tabl-tbl",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "frozen functionaly so no drastic cleanup",
+ filename = "tabl-ntb",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "tabl-mis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "tabl-nte",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be redone when needed",
+ filename = "tabl-ltb",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ comment = "will be adapted when needed (and rest is done)",
+ filename = "tabl-tsp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "tabl-xtb",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "tabl-xnt",
+ loading = "module",
+ status = "okay",
+ loading = "always",
+ comment = "only when natural tables need a replacement",
+ },
+ {
+ category = "mkiv",
+ filename = "java-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-fld",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "namespace needs checking",
+ filename = "scrn-hlp",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "char-enc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-lib",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-fil",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-var",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-fea",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-mat",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "needs occasional checking and upgrading",
+ filename = "font-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-sym",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-sty",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-set",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-emp",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-col",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "font-pre",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "font-unk",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "likely this will become a module",
+ filename = "font-tra",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this could become a module",
+ filename = "font-chk",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this one might be merged",
+ filename = "font-uni",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-col",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-gds",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "font-aux",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this is work in progress",
+ filename = "lxml-css",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-chr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-cha",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "work in progress",
+ filename = "blob-ini",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "trac-vis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "trac-vis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-cln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-spa",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "do we keep the style and color or not",
+ filename = "typo-krn",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "typo-itc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe singular setup",
+ filename = "typo-dir",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-brk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-cap",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-dig",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-rep",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "maybe there will be a nicer interface",
+ filename = "typo-txt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might get extended",
+ filename = "typo-par",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "type-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-set",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-def",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-fbk",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-lua",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-one",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-otf",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-siz",
+ loading = "type-set",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-tmf",
+ loading = "never",
+ status = "okay",
+ comment = "placeholder to prevent other loading",
+ },
+ {
+ category = "mkiv",
+ filename = "scrp-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this module is obsolete",
+ filename = "prop-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mlib-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "metapost code is always evolving",
+ filename = "meta-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code used in a project",
+ filename = "meta-lua",
+ loading = "experimental",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-tex",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe this one will be merged",
+ filename = "meta-fun",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might get updated when mp code gets cleaned up",
+ filename = "meta-pag",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-grd",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-mrk",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-flw",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-spr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be made better",
+ filename = "page-plg",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs more work (and thinking)",
+ filename = "page-str",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "in transition",
+ filename = "anch-pgr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ comment = "in transition",
+ filename = "anch-bck",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will stay experimental for a while",
+ filename = "anch-tab",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "anch-bar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "interesting old mechanism to keep around (module?)",
+ filename = "anch-snc",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "math-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this file might merge into others",
+ filename = "math-pln",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "math-for",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "eventually this will be split and spread",
+ filename = "math-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will be checked and improved",
+ filename = "math-ali",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs testing",
+ filename = "math-arr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "at least for the moment",
+ filename = "math-frc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "math-scr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "math-int",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code get replaced (by autodelimiters)",
+ filename = "math-del",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code might move to here",
+ filename = "math-inl",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "code might move to here",
+ filename = "math-dis",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "phys-dim",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "some more functionality will end up here",
+ filename = "strc-mat",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "chem-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "chem-str",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-scr",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "maybe some cleanup is needed",
+ filename = "node-rul",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "needs testing",
+ filename = "font-sol",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkvI",
+ filename = "strc-not",
+ loading = "always",
+ status = "todo",
+ },
+ {
+ category = "mkvi",
+ comment = "will be extended as part of crited",
+ filename = "strc-lnt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-com",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "typo-del",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "grph-trf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "grph-inc",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "grph-fig",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "grph-raw",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-box",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "pack-bar",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "page-app",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-fig",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "more or less obsolete",
+ filename = "lang-spa",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "bibl-bib",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ filename = "bibl-tra",
+ loading = "always",
+ status = "pending",
+ },
+ {
+ category = "mkiv",
+ comment = "not needed",
+ filename = "meta-xml",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cont-log",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "task-ini",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cldf-ver",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "cldf-com",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "core-ctx",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "will always be messy",
+ filename = "core-def",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "object related code might move or change",
+ filename = "back-pdf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "back-swf",
+ loading = "never",
+ status = "okay",
+ comment = "no code, just an example of usage",
+ },
+ {
+ category = "mkiv",
+ filename = "back-u3d",
+ loading = "never",
+ status = "okay",
+ comment = "no code, just an example of usage",
+ },
+ {
+ category = "mkiv",
+ filename = "mlib-pdf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "mlib-pps",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-pdf",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "might need more work",
+ filename = "grph-epd",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "some parameters might move from export to backend",
+ filename = "back-exp",
+ loading = "always",
+ status = "okay",
+ },
+ },
+ extras = {
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-arrange",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-combine",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-common",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-ideas",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-listing",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-markdown",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-select",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ comment = "add-on for mtx-context",
+ filename = "mtx-context-timing",
+ loading = "on demand",
+ status = "okay",
+ },
+ },
+ implementations = {
+ {
+ category = "mkiv",
+ filename = "colo-imp-dem",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-imp-ema",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-imp-rgb",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-imp-x11",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-imp-xwi",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-exa",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-fil",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-fld",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-rhh",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "java-imp-stp",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-clp",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-dum",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-fen",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-mis",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-nav",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-pre",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-imp-txt",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-cow",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-eur",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-jmn",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-mis",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-mvs",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-imp-nav",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-antykwa",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-antykwapoltawskiego",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-asana",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-averia",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-buy",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-cambria",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-charter",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-cleartype",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-computer-modern-unicode",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-cow",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-dejavu",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-euler",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-ghz",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-hgz",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-husayni",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-hvmath",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-inconsolata",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-informal",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-iwona",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-kurier",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-latinmodern",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-liberation",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-libertine",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-lmnames",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-lucida-opentype",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-lucida-typeone",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-mathdesign",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-mathtimes",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-mscore",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-osx",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-postscript",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-punknova",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-texgyre",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-unfonts",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-xits",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-imp-xitsbidi",
+ loading = "on demand",
+ status = "okay",
+ },
+ },
+ lua = {
+ {
+ category = "lua",
+ filename = "anch-pgr",
+ loading = "anch-pgr",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "anch-pos",
+ loading = "anch-pos",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-col",
+ loading = "attr-col",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-eff",
+ loading = "attr-eff",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-ini",
+ loading = "attr-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-lay",
+ loading = "attr-lay",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "attr-neg",
+ loading = "attr-neg",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "experimental code, maybe some will move elsewhere",
+ filename = "back-exp",
+ loading = "back-exp",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "back-ini",
+ loading = "back-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "back-pdf",
+ loading = "back-pdf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "bibl-bib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "bibl-tra",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "blob-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "buff-imp-default",
+ loading = "buff-imp-default",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-imp-escaped",
+ loading = "buff-imp-escaped",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "todo: colorization and nesting as in scite",
+ filename = "buff-imp-lua",
+ loading = "buff-imp-lua",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "todo: colorization and nesting as in scite",
+ filename = "buff-imp-mp",
+ loading = "buff-imp-mp",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-imp-nested",
+ loading = "buff-imp-nested",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-imp-parsed-xml",
+ loading = "buff-imp-parsed-xml",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "todo: colorization and nesting as in scite",
+ filename = "buff-imp-tex",
+ loading = "buff-imp-tex",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "todo: colorization and nesting as in scite",
+ filename = "buff-imp-xml",
+ loading = "buff-imp-xml",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "buff-par",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe we will provide a few more (nesting) methods",
+ filename = "buff-ver",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "catc-ini",
+ loading = "catc-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-cjk",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-def",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe dataonly",
+ filename = "char-enc",
+ loading = "char-enc",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-ent",
+ loading = "char-ent",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe move blocks table to separate (dataonly) file",
+ filename = "char-ini",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-map",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-tex",
+ loading = "char-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "char-utf",
+ loading = "char-utf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "chem-ini",
+ loading = "chem-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "chem-str",
+ loading = "chem-str",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "will be extended and can be optimized if needed",
+ filename = "cldf-bas",
+ loading = "cldf-bas",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "might change or even go away",
+ filename = "cldf-com",
+ loading = "cldf-com",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "cldf-ini",
+ loading = "cldf-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "cldf-int",
+ loading = "cldf-int",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "maybe this code can be redone more efficiently/robust",
+ filename = "cldf-ver",
+ loading = "cldf-ver",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "also used in mtx-*",
+ filename = "colo-icc",
+ loading = "colo-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "colo-ini",
+ loading = "colo-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "this code might move to a module",
+ filename = "colo-run",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "core-con",
+ loading = "core-con",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "core-ctx",
+ loading = "core-ctx",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "core-dat",
+ loading = "core-dat",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe abusing the tex namespace is wrong",
+ filename = "core-env",
+ loading = "core-env",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "core-sys",
+ loading = "core-sys",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ commands = "this is in fact replaced by core-dat",
+ filename = "core-two",
+ loading = "core-two",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "some code will move to better places",
+ filename = "core-uti",
+ loading = "core-uti",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "data-aux",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-bin",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-con",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-crl",
+ loading = "never",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-ctx",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-env",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-exp",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-fil",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-gen",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-ini",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-inp",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-lst",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-lua",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-met",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-out",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-pre",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-res",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-sch",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-tex",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-tmf",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-tmp",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-tre",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-use",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-vir",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "data-zip",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "file-ini",
+ loading = "file-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-job",
+ loading = "file-job",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-lib",
+ loading = "file-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-mod",
+ loading = "file-mod",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-res",
+ loading = "file-res",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "file-syn",
+ loading = "file-syn",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-afm",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-afk",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "only used in luatex-fonts",
+ filename = "font-age",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-agl",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "needs some documentation in usage",
+ filename = "font-aux",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "move more to the commands namespace",
+ filename = "font-chk",
+ loading = "font-chk",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-cid",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-col",
+ loading = "font-col",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-con",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "will be improved over time",
+ filename = "font-ctx",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-def",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "part of this code is obsolete",
+ filename = "font-enc",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "needs documentation at the tex end",
+ filename = "font-enh",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe some data tables can be be external",
+ filename = "font-ext",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "okay but can be improved",
+ filename = "font-fbk",
+ loading = "font-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "font-gds",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-ini",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-ldr",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-log",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "currently rather minimalistic",
+ filename = "font-lua",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "the lum file support will be dropped / no map files anyway",
+ filename = "font-map",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-mis",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "when more scripts are supported we might end up with imp files",
+ filename = "font-ota",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otb",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otc",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otd",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otf",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-oth",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-oti",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otn",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-otp",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-ott",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "is mostly replaced by lfg files",
+ filename = "font-pat",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-sol",
+ loading = "font-sol",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "also loaded on demand",
+ filename = "font-syn",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-tfm",
+ loading = "font-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "font-vf",
+ loading = "font-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "grph-epd",
+ loading = "grph-epd",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "grph-fil",
+ loading = "grph-inc",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "grph-inc",
+ loading = "grph-inc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "grph-raw",
+ loading = "grph-raw",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "grph-swf",
+ loading = "grph-swf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "grph-u3d",
+ loading = "grph-u3d",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "experiment with graphic magick library",
+ filename = "grph-wnd",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "java-ini",
+ loading = "java-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "l-boolean",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-dir",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-file",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-io",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-lpeg",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-math",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-md5",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-number",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-os",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-pdfview",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-set",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-string",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-table",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-unicode",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-url",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "l-xml",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lang-def",
+ loading = "lang-def",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-ini",
+ loading = "lang-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-lab",
+ loading = "lang-lab",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lang-txt",
+ loading = "lang-lab",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe another approach is nicer",
+ filename = "lang-url",
+ loading = "lang-url",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "lang-wrd",
+ loading = "lang-wrd",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "more will end up here",
+ filename = "layo-ini",
+ loading = "layo-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-ano",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-col",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-enc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-epa",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-epd",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-fld",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-fmt",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-grp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-mis",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-mov",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-nod",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-ren",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-swf",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-tag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-u3d",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-wid",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lpdf-xmp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ comment = "replacement code for wd/ht/dp",
+ filename = "luat-bwc",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-cbk",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-cnf",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "maybe some code should move",
+ filename = "luat-cod",
+ loading = "luat-cod",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-env",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-exe",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-fio",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-fmt",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "will be upgraded when we have Lua 5.2",
+ filename = "luat-ini",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "luat-iop",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "this is likely to change some day",
+ filename = "luat-lua",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-mac",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-run",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "related to the socket code",
+ filename = "luat-soc",
+ loading = "on demand",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "luat-sta",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "luat-sto",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "lxml-aux",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-css",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-ctx",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-dir",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-ent",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-inf",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-lpt",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-mis",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-sor",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-tab",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-tex",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "lxml-xml",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-chart",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-database",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-markdown",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-pstricks",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-spreadsheet",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "m-steps",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "math-act",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "could be made look nicer, but who cares",
+ filename = "math-dim",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "the code is related to math-vfu",
+ filename = "math-ext",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-fbk",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "okay, but we might have a few more low level definers some day",
+ filename = "math-ini",
+ loading = "math-ini",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "math-map",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-noa",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-ren",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-tag",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-ttv",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "math-vfu",
+ loading = "math-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "this is just a first version",
+ filename = "meta-fun",
+ loading = "meta-fun",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "meta-ini",
+ loading = "meta-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "meta-lua",
+ loading = "meta-lua",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "could be done nicer nowadays but who needs it",
+ filename = "meta-pdf",
+ loading = "meta-pdf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "meta-pdh",
+ loading = "meta-pdh",
+ status = "okay",
+ loading = "never",
+ comment = "this is historic code that we keep around",
+ },
+ {
+ category = "lua",
+ filename = "meta-tex",
+ loading = "meta-tex",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mlib-ctx",
+ loading = "mlib-ctx",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mlib-pdf",
+ loading = "mlib-pdf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mlib-pps",
+ loading = "mlib-pdf",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mlib-run",
+ loading = "mlib-ctx",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "this is an experiment, namespaces need to be dealt with properly",
+ filename = "mult-aux",
+ loading = "mult-aux",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "this is an experiment",
+ filename = "mult-chk",
+ loading = "mult-chk",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "mult-def",
+ loading = "mult-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "used for generating editor lexing files",
+ filename = "mult-fun",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "mult-ini",
+ loading = "mult-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "used for generating editor lexing files",
+ filename = "mult-low",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "all messages need to be checked",
+ filename = "mult-mes",
+ loading = "mult-ini",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "used for generating editor lexing files",
+ filename = "mult-mps",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "used for generating editor lexing files",
+ filename = "mult-prm",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "node-acc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-aux",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-bck",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-dir",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ext",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-fin",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-fnt",
+ loading = "font-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-inj",
+ loading = "font-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-mig",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-pag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-pro",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ref",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-res",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-rul",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-ser",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-shp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-tex",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-tra",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-tsk",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-tst",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "node-typ",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ comment = "will be extended when we have opened up pdf objects",
+ filename = "pack-obj",
+ loading = "pack-obj",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "pack-rul",
+ loading = "pack-rul",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "page-flt",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-ins",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-lin",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-mix",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-pst",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "page-str",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "phys-dim",
+ loading = "phys-dim",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-1",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-10",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-11",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-13",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-14",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-15",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-16",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-2",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-3",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-4",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-5",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-6",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-7",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-8",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-8859-9",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1250",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1251",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1252",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1253",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1254",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1255",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1256",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1257",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-cp1258",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "just a demo file",
+ filename = "regi-demo",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "regi-ini",
+ loading = "regi-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "s-fonts-tables",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "s-pre-71",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-but",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-fld",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-hlp",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-pag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-ref",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "scrn-wid",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ comment = "we can speed this up",
+ filename = "scrp-cjk",
+ loading = "scrp-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "we can speed this up",
+ filename = "scrp-eth",
+ loading = "scrp-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "scrp-ini",
+ loading = "scrp-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "sort-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "sort-lan",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-adj",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-ali",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-chr",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-hor",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "spac-ver",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "status-mkiv",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-bkm",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-blk",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-con",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-doc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-flt",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-itm",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-lev",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-lst",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-mar",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-mat",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-not",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-num",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-pag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-ref",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-reg",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-rsc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-syn",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "strc-tag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "supp-box",
+ loading = "supp-box",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "supp-ran",
+ loading = "supp-ran",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "symb-ini",
+ loading = "symb-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "there will be more in here",
+ filename = "syst-aux",
+ loading = "syst-aux",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "do some tests with speedups (sprint)",
+ filename = "syst-con",
+ loading = "syst-con",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "do some tests with speedups (less tokens)",
+ filename = "syst-lua",
+ loading = "syst-lua",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "tabl-tbl",
+ loading = "tabl-tbl",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "work in progress",
+ filename = "tabl-xtb",
+ loading = "tabl-xtb",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "we need a well defined defintion moment",
+ filename = "task-ini",
+ loading = "task-ini",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "toks-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ comment = "must be applied in more places",
+ filename = "trac-ctx",
+ loading = "trac-ctx",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-deb",
+ loading = "trac-deb",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "for the moment somewhat private",
+ filename = "trac-fil",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-inf",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "will be redone and extended",
+ filename = "trac-lmx",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "trac-log",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ comment = "experimental code, will be redone when lua 5.2",
+ filename = "trac-pro",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ comment = "some code can better be in util-set",
+ filename = "trac-set",
+ loading = "luat-lib",
+ status = "pending",
+ },
+ {
+ category = "lua",
+ filename = "trac-tex",
+ loading = "trac-tex",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-tim",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "trac-vis",
+ loading = "trac-vis",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "type-ini",
+ loading = "type-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "typo-bld",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-brk",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-cap",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-cln",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-dig",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-dir",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-ini",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-itc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-krn",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-mar",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-pag",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-par",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-prc",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-rep",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "typo-spa",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "unic-ini",
+ loading = "unic-ini",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "util-deb",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-dim",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-fmt",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-jsn",
+ loading = "m-json",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-lua",
+ loading = "luat-lib",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "util-mrg",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-pck",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-prs",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-seq",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-sql",
+ loading = "m-sql",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-sta",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-sto",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-str",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-tab",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "util-tpl",
+ loading = "luat-lib",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-asciimath",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-calcmath",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-cals",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-chemml",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-ct",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-ldx",
+ status = "todo",
+ },
+ {
+ category = "lua",
+ filename = "x-mathml",
+ status = "todo",
+ },
+ },
+ metafun = {
+ {
+ category = "mpiv",
+ filename = "mp-base",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-tool",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-mlib",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "sort of obsolete",
+ filename = "mp-core",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "maybe some nicer synonyms",
+ filename = "mp-page",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-butt",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-shap",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-grph",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-grid",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "a hack anyway",
+ filename = "mp-form",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-figs",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-func",
+ loading = "always",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-text",
+ loading = "on demand",
+ status = "todo",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-crop",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "follows m-chart",
+ filename = "mp-char",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "follows m-steps",
+ filename = "mp-step",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ filename = "mp-chem",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "maybe some namespace changes",
+ filename = "mp-abck",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "maybe some namespace changes",
+ filename = "mp-apos",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mpiv",
+ comment = "will be done when needed",
+ filename = "mp-asnc",
+ loading = "on demand",
+ status = "todo",
+ },
+ },
+ modules = {
+ {
+ category = "mkiv",
+ comment = "best use m-zint instead",
+ filename = "m-barcodes",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "m-chart",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "this is a placeholder (chemistry is built-in)",
+ filename = "m-chemic",
+ loading = "never",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-cweb",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-database",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-datastrc",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "add-on for mtx-context",
+ filename = "m-directives",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-educat",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-fields",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-format",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-graph",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-ipsum",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-json",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-layout",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "add-on for mtx-context",
+ filename = "m-logcategories",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-markdown",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-mathcrap",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-mkii",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-mkivhacks",
+ status = "todo",
+ },
+ {
+ category = "mkvi",
+ filename = "m-morse",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-narrowtt",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-newmat",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-ntb-to-xtb",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-obsolete",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-oldfun",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-oldnum",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-pictex",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-pstricks",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "keep an eye on changes in lua code",
+ filename = "m-punk",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "m-r",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-spreadsheet",
+ status = "okay",
+ },
+ {
+ category = "mkvi",
+ filename = "m-steps",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-streams",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "m-subsub",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-sql",
+ loading = "module",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-timing",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "add-on for mtx-context",
+ filename = "m-trackers",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-translate",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-units",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-visual",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "m-zint",
+ status = "okay",
+ },
+ {
+ category = "tex",
+ filename = "s-abr-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-abr-02",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-abr-03",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-abr-04",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-art-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-cdr-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-def-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-faq-00",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-faq-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-faq-02",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-faq-03",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-10",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-11",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-20",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-21",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-23",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-24",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-26",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-28",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-29",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-30",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-31",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fnt-32",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-missing",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-fonts-tables",
+ status = "todo",
+ },
+ {
+ category = "mkvi",
+ filename = "s-inf-01",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "s-inf-02",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-inf-03",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-inf-04",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-lan-03",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-lan-04",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-mag-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-map-10",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mat-10",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mat-11",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mat-12",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mod-00",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mod-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-mod-02",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-phy-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-00",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-01",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-02",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-03",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-04",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-05",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-06",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-07",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-08",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-09",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-10",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-11",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-12",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-13",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-14",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-15",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-16",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-17",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-18",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-19",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-22",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-23",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-26",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-27",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-30",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-50",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-60",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-61",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-62",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-63",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-64",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-66",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-67",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-68",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-69",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-70",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-pre-71",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-93",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-pre-96",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-ptj-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-reg-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "s-set-31",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "s-syn-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-asciimath",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-calcmath",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-cals",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-chemml",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-ct",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "x-dir-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-dir-05",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-entities",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-foxet",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-ldx",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-mathml",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-newmml",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ comment = "pfsense xml configuration rendering",
+ filename = "x-pfs-01",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-physml",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-res-01",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-res-50",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-set-11",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-set-12",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "x-udhr",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "x-xtag",
+ status = "todo",
+ },
+ },
+ optional = {
+ {
+ category = "mkiv",
+ filename = "bxml-apa",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "colo-run",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ comment = "always needs some work",
+ filename = "cont-new",
+ loading = "runtime",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "font-run",
+ loading = "on demand",
+ status = "todo",
+ },
+ {
+ category = "mkiv",
+ filename = "lxml-ctx",
+ status = "okay",
+ comment = "this is an experimental module",
+ },
+ {
+ category = "mkiv",
+ filename = "meta-pdh",
+ loading = "never",
+ status = "okay",
+ comment = "this is historic code that we keep around",
+ },
+ {
+ category = "mkiv",
+ filename = "mult-prm",
+ loading = "never",
+ status = "okay",
+ comment = "this is just a helper for generating files",
+ },
+ {
+ category = "mkiv",
+ filename = "page-run",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "spac-adj",
+ loading = "never",
+ status = "obsolete",
+ },
+ {
+ category = "mkiv",
+ filename = "supp-vis",
+ loading = "never",
+ status = "obsolete",
+ comment = "replaced by a more modern variant",
+ },
+ {
+ category = "mkiv",
+ filename = "symb-run",
+ loading = "on demand",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "type-run",
+ loading = "on demand",
+ status = "todo",
+ },
+ },
+ resources = {
+ {
+ category = "ori",
+ comment = "template for a user configuration file (with suffix mkiv)",
+ filename = "cont-sys",
+ loading = "runtime",
+ status = "okay",
+ },
+ {
+ category = "lmx",
+ filename = "context-base",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-characters",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-debug",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-error",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-fonttest",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-help",
+ status = "todo",
+ },
+ {
+ category = "lmx",
+ filename = "context-timing",
+ status = "todo",
+ },
+ {
+ category = "pdf",
+ filename = "context-version",
+ status = "todo",
+ },
+ {
+ category = "png",
+ filename = "context-version",
+ status = "todo",
+ },
+ {
+ category = "css",
+ comment = "layout specification for debug and error pages and web services",
+ filename = "context",
+ status = "okay",
+ },
+ {
+ category = "rme",
+ comment = "readme file",
+ filename = "context",
+ status = "okay",
+ },
+ {
+ category = "ctx",
+ comment = "example of a ctx file (for mtx-context)",
+ filename = "core-ctx",
+ status = "okay",
+ },
+ {
+ category = "css",
+ filename = "export-example",
+ status = "todo",
+ },
+ {
+ category = "rng",
+ filename = "export-example",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "export-example",
+ status = "todo",
+ },
+ {
+ category = "xml",
+ comment = "this file is auto-generated by mtx-language",
+ filename = "lang-all",
+ status = "okay",
+ },
+ {
+ category = "xml",
+ filename = "lpdf-pda",
+ status = "todo",
+ },
+ {
+ category = "xml",
+ filename = "lpdf-pdx",
+ status = "todo",
+ },
+ {
+ category = "rlx",
+ filename = "rlxcache",
+ status = "todo",
+ },
+ {
+ category = "rlx",
+ filename = "rlxtools",
+ status = "todo",
+ },
+ {
+ category = "ctx",
+ filename = "s-mod",
+ status = "todo",
+ },
+ {
+ category = "pdf",
+ filename = "status-files",
+ status = "todo",
+ },
+ {
+ category = "pdf",
+ filename = "status-lua",
+ status = "todo",
+ },
+ {
+ category = "tex",
+ filename = "status-mkiv",
+ status = "todo",
+ },
+ {
+ category = "xsd",
+ filename = "x-chemml",
+ status = "todo",
+ },
+ {
+ category = "xsd",
+ filename = "x-contml",
+ status = "todo",
+ },
+ {
+ category = "rng",
+ filename = "x-corres",
+ status = "todo",
+ },
+ {
+ category = "dtd",
+ filename = "x-fig-00",
+ status = "todo",
+ },
+ {
+ category = "xsd",
+ filename = "x-fig-00",
+ status = "todo",
+ },
+ {
+ category = "ctx",
+ filename = "x-ldx",
+ status = "todo",
+ },
+ {
+ category = "xsd",
+ filename = "x-mathml",
+ status = "todo",
+ },
+ {
+ category = "xsl",
+ filename = "x-om2cml",
+ status = "todo",
+ },
+ {
+ category = "xsl",
+ filename = "x-openmath",
+ status = "todo",
+ },
+ {
+ category = "ctx",
+ comment = "runner for x-pfs-01",
+ filename = "x-pfsense",
+ status = "okay",
+ },
+ {
+ category = "xsd",
+ filename = "x-physml",
+ status = "todo",
+ },
+ {
+ category = "xsl",
+ filename = "x-sm2om",
+ status = "todo",
+ },
+ },
}
diff --git a/tex/context/base/status-mkiv.tex b/tex/context/base/status-mkiv.tex
index 0d22d51a1..7ca394a19 100644
--- a/tex/context/base/status-mkiv.tex
+++ b/tex/context/base/status-mkiv.tex
@@ -1,38 +1,46 @@
- \setupbodyfont[dejavu,10pt]
+\usemodule[abr-02]
+
+\setupbodyfont
+ [dejavu,9pt]
+
+\setuppapersize
+ [A4,landscape]
\setuplayout
[width=middle,
height=middle,
- backspace=1cm,
- topspace=1cm,
+ backspace=.5cm,
+ topspace=.5cm,
footer=0pt,
header=1.25cm]
\setuphead
- [subject]
+ [title]
[style=\bfa,
- page=yes]
+ page=yes,
+ after={\blank[line]}]
\setuppagenumbering
[location=]
\setupheadertexts
- [\currentdate][MkIV cleanup Status / Page \pagenumber]
+ [\currentdate]
+ [MkIV Status / Page \pagenumber]
+
+% \showmakeup
+% \showallmakeup
\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
+% logs.report (immediate) versus logs.messenger (in flow)
-\startsubject[title=Todo]
+\starttitle[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
@@ -40,122 +48,272 @@
\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
+ \startitem maybe rename dowhatevertexcommand to fromluawhatevertexcommand \stopitem
+ \startitem consider moving setups directly to lua end (e.g. in characterspacing, breakpoint, bitmaps etc.) \stopitem
+ \startitem more local temporary \type {\temp...} will become \type {\p_...} \stopitem
+ \startitem check all ctxlua calls for ctxcommand \stopitem
+ \startitem rename all those \type {\current<whatever>}s in strc \stopitem
+ \startitem check \type {option} vs \type {options} \stopitem
+ \startitem check \type {type} vs \type {kind} \stopitem
+ \startitem check \type {label} vs \type {name} vs \type {tag} \stopitem
+ \startitem check \type {limop}, different limops should should be classes \stopitem
+ \startitem too many positions in simple files (itemize etc) \stopitem
+ \startitem math domains/dictionaries \stopitem
+ \startitem xtables don't span vertically with multilines (yet) \stopitem
+ \startitem notes in mixed columns \stopitem
+ \startitem floats in mixed columns \stopitem
+ \startitem check return values \type {os.execute} \stopitem
+ \startitem more r, d, k in xml code \stopitem
+ \startitem mathml, more in \LUA \stopitem
+ \startitem style: font-size, font, color handling in \HTML\ (lxml-css) \stopitem
+ \startitem a \type {\name {A.B.C DEF}} auto-nobreakspace \stopitem
+ \startitem redo \CWEB\ module with \LUA \stopitem
+ \startitem maybe move characters.blocks to its own file \stopitem
+ \startitem more local context = context in \LUA\ files \stopitem
+ \startitem check and optimize all storage.register and locals (cosmetics) \stopitem
+ \startitem check all used modules in \LUA\ (and local them) \stopitem
+ \startitem environment and basic lua helpers are now spread over too many files \stopitem
+ \startitem isolate tracers and showers \stopitem
+ \startitem check all possible usage of ctxcommand \stopitem
+ \startitem there are more s-* modules, like s-fnt-41 \stopitem
+ \startitem check (un)marked tables \stopitem
\stopitemize
-\stopsubject
+\stoptitle
-\startsubject[title=Status]
+\definehighlight[notabenered] [color=darkred, style=bold]
+\definehighlight[notabeneblue] [color=darkblue, style=bold]
+\definehighlight[notabeneyellow] [color=darkyellow, style=bold]
+\definehighlight[notabenemagenta][color=darkmagenta,style=bold]
\startluacode
local coremodules = dofile("status-mkiv.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", "norm", "catc",
+ "cldf", "file", "char", "core", "layo", "trac", "cont", "regi", "enco", "hand",
+ "unic", "sort", "blob", "type", "scrp", "prop", "chem", "bibl", "task",
+ "whatever", "mp", "s", "x", "m", "mtx",
+ }
+
+ local specialcategories = {
+ mkvi = true,
+ }
+
+ local what = {
+ "main", "core", "lua", "optional", "implementations", "extra", "extras", "metafun", "modules", "resources"
+ }
+
+ local totaltodo = 0
+ local totalpending = 0
+ local totalobsolete = 0
+ local totalloaded = 0
+
+ local function summary(nofloaded,noftodo,nofpending,nofobsolete)
+
+ local nofdone = nofloaded - noftodo - nofpending - nofobsolete
+
+ context.starttabulate { "|B|r|" }
+ context.HL()
+ context.NC() context("done") context.NC() context(nofdone) context.NC() context.NR()
+ context.NC() context("todo") context.NC() context(noftodo) context.NC() context.NR()
+ context.NC() context("pending") context.NC() context(nofpending) context.NC() context.NR()
+ context.NC() context("obsolete") context.NC() context(nofobsolete) context.NC() context.NR()
+ context.HL()
+ context.NC() context("loaded") context.NC() context(nofloaded) context.NC() context.NR()
+ context.HL()
+ context.stoptabulate()
+
+ end
+
if coremodules then
local function tabelize(loaded,what)
if loaded then
- local nofunknown = 0
- local nofloaded = #loaded
+ local noftodo = 0
+ local nofpending = 0
+ local nofobsolete = 0
+ local nofloaded = #loaded
+ local categories = { }
+
+ for k, v in next, valid do
+ categories[k] = { }
+ end
for i=1,nofloaded do
- loaded[i].order = i
+ local l = loaded[i]
+ l.order = i
+ local category = string.match(l.filename,"([^%-]+)%-") or "whatever"
+ local c = categories[category]
+ if c then
+ c[#c+1] = l
+ end
end
- table.sort(loaded,function(a,b) return a.filename < b.filename end)
+ for k, loaded in table.sortedhash(categories) do
+
+ local nofloaded = #loaded
+
+ if nofloaded > 0 then
+
+ table.sort(loaded,function(a,b) return a.filename < b.filename end) -- in place
+
+ context.starttitle { title = string.format("%s: %s",what,k) }
+
+ context.starttabulate { "|Tr|Tlw(3em)|Tlw(12em)|Tlw(12em)|Tlw(4em)|Tl|Tl|Tl|Tp|" }
+ context.NC() context.bold("order")
+ context.NC() context.bold("kind")
+ context.NC() context.bold("file")
+ context.NC() context.bold("loading")
+ context.NC() context.bold("status")
+ context.NC() context.bold("reference")
+ context.NC() context.bold("manual")
+ context.NC() context.bold("wiki")
+ context.NC() context.bold("comment")
+ context.NC() context.NR()
+ context.HL()
+ for i=1,nofloaded do
+ local module = loaded[i]
+ local status = module.status
+ local category = module.category
+ local filename = module.filename
+ context.NC()
+ context(module.order)
+ context.NC()
+ if specialcategories[category] then
+ context.notabeneblue(category)
+ else
+ context(category)
+ end
+ context.NC()
+ if #filename>20 then
+ context(string.sub(filename,1,18) .. "..")
+ else
+ context(filename)
+ end
+ context.NC()
+ context(module.loading)
+ context.NC()
+ if status == "todo" then
+ context.notabenered(status)
+ noftodo = noftodo + 1
+ elseif status == "pending" then
+ context.notabeneyellow(status)
+ nofpending = nofpending + 1
+ elseif status == "obsolete" then
+ context.notabenemagenta(status)
+ nofobsolete = nofobsolete + 1
+ else
+ context(status)
+ end
+ context.NC() context(module.reference)
+ context.NC() context(module.manual)
+ context.NC() context(module.wiki)
+ context.NC() context(module.comment)
+ context.NC() context.NR()
+ end
+ context.stoptabulate()
+
+ context.stoptitle()
- 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.starttitle { title = string.format("summary of %s modules",what) }
- context("Of the %s %s modules (so far) in this list %s have the status unknown",nofloaded,what,nofunknown)
+ summary(nofloaded,noftodo,nofpending,nofobsolete)
+
+ context.stoptitle()
+
+ totaltodo = totaltodo + noftodo
+ totalpending = totalpending + nofpending
+ totalobsolete = totalobsolete + nofobsolete
+ totalloaded = totalloaded + nofloaded
end
end
- tabelize(coremodules.core, "core")
- tabelize(coremodules.extra,"extra")
+ for i=1,#what do
+ tabelize(coremodules[what[i]],what[i])
+ end
end
- local namespaces = dofile("status-namespaces.lua")
+ -- context.starttitle { title = "Valid prefixes" }
+ --
+ -- for namespace, data in table.sortedhash(namespaces) do
+ -- if valid[namespace] then
+ -- context.type(namespace)
+ -- end
+ -- context.par()
+ -- end
+ --
+ -- context.stoptitle()
- 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.starttitle { title = string.format("summary of all",what) }
- context.startsubject { title = "Valid prefixes" }
+ summary(totalloaded,totaltodo,totalpending,totalobsolete)
- for namespace, data in table.sortedhash(namespaces) do
- if valid[namespace] then
- context.type(namespace)
- end
- context.par()
- end
+ context.stoptitle()
- context.stopsubject()
+ if io.exists("status-namespaces.lua") then
- context.startsubject { title = "Messy namespaces" }
+ context.starttitle { title = "messy namespaces" }
- for namespace, data in table.sortedhash(namespaces) do
- if valid[namespace] then
- else
- context(namespace)
+ local namespaces = dofile("status-namespaces.lua")
+
+ for namespace, data in table.sortedhash(namespaces) do
+ if valid[namespace] then
+ else
+ context(namespace)
+ end
+ context.par()
end
- context.par()
+
+ context.stoptitle()
+
end
- context.stopsubject()
+ if io.exists("status-registers.lua") then
- local registers = dofile("status-registers.lua")
+ context.starttitle { title = "messy registers" }
- 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)
+ local registers = dofile("status-registers.lua")
+
+ 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
- context.par()
+
+ context.stoptitle()
+
end
+ context.starttitle { title = "callbacks" }
+
+ commands.showcallbacks()
+
+ context.stoptitle()
+
\stopluacode
-\stopsubject
\stoptext
diff --git a/tex/context/base/strc-bkm.mkiv b/tex/context/base/strc-bkm.mkiv
index 8ddf0a6df..8e1252329 100644
--- a/tex/context/base/strc-bkm.mkiv
+++ b/tex/context/base/strc-bkm.mkiv
@@ -11,93 +11,109 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This might become scrn-bkm.mkiv.
-
\writestatus{loading}{ConTeXt Structure Macros / Bookmarks}
\registerctxluafile{strc-bkm}{1.001}
\unprotect
-%D Due to requests I finally decided to support bookmarks, a
-%D driver dependant way of showing tables of content. The most
-%D simple way of support is hooking bookmark generation into
-%D the existing list mechanisms. That way users can generate
-%D bookmarks automatically, although its entirely valid to add
-%D bookmarks by defining alternative ones. These will be added
-%D at the appropriate place in the list.
-
-% \hoofdstuk{het eerste hoofdstuk}
-%
-% \bookmark {de eerste bookmark} % optional overruled hoofdstuk
-%
-% .... text ....
-%
-% \placebookmarks [hoofdstuk,paragraaf,subparagraaf,subsubparagraaf,mylist]
-% [open list]
-%
-% \bookmark[mylist]{whatever}
-
-%D This will go away.
-
-\let\flushpostponedbookmark\relax
+%D Bookmarks are a very viewer dependent feature. They are mostly used
+%D as additional table of contents and therefore relate directly to lists.
+%D
+%D A bookmark list is added to the document only when interaction is
+%D enabled. The given lists are bookmarked and a second argument specifies
+%D the opened bookmark trees.
+%D
+%D \starttyping
+%D \placebookmarks
+%D [chapter,section,subsection,mylist]
+%D [chapter]
+%D \stoptyping
+%D
+%D You can overloads the last set bookmark in a sectioning command:
+%D
+%D \starttyping
+%D \chapter {the first chapter}
+%D \bookmark {the first bookmark}
+%D \stoptyping
+%D
+%D However, in practice you can better use \type {\startchapter} and set the
+%D \type {bookmark} parameter.
+%D
+%D You can add entries to the bookmarklist:
+%D
+%D \starttyping
+%D \bookmark[mylist]{whatever}
+%D \stoptyping
+%D
+%D Use force to get titles in the bookmarklist. This is somewhat tricky as
+%D one does not want "Contents" in a table of contents but it has to be in
+%D the bookmark list.
+
+\installcorenamespace{bookmark}
+
+\installsetuponlycommandhandler \??bookmark {bookmark} % installdirectparametersethandler
+
+\setupbookmark
+ [\c!force=\v!no, % it's easier to force that to inhibit
+ \c!number=\v!yes] % might become v!no
-%D We have better ways now.
+\let\setupbookmarks\setupbookmark
\unexpanded\def\bookmark
- {\dosingleempty\dobookmark}
+ {\dosingleempty\strc_bookmarks_bookmark}
-\def\dobookmark[#1]#2%
+\def\strc_bookmarks_bookmark
+ {\iflocation
+ \expandafter\strc_bookmarks_bookmark_yes
+ \else
+ \expandafter\strc_bookmarks_bookmark_nop
+ \fi}
+
+\def\strc_bookmarks_bookmark_yes[#1]#2%
{\begingroup
\simplifycommands
\ctxcommand{overloadbookmark("#1",\!!bs\detokenize\expandafter{\normalexpanded{#2}}\!!es)}%
\endgroup}
-%D Placement \unknown\ look how simple compared to \MKII:
-
-\newtoks \everysetupbookmarks
-
-\def\bookmarkparameter#1{\ifcsname\??bm#1\endcsname\csname\??bm#1\endcsname\fi}
-
-\unexpanded\def\setupbookmarks[#1]%
- {\getparameters[\??bm][#1]%
- \the\everysetupbookmarks}
+\def\strc_bookmarks_bookmark_nop[#1]#2%
+ {}
\unexpanded\def\placebookmarks
- {\dotripleempty\doplacebookmarks}
-
-% Use force to get titles in the bookmarklist. This is somewhat tricky as one
-% does not want "Contents" in a table of contents but it has to be in the
-% bookmark list.
+ {\dotripleempty\strc_bookmarks_place}
-\def\doplacebookmarks[#1][#2][#3]%
+\def\strc_bookmarks_place
{\iflocation
- \begingroup
- \edef\askednames{#1}%
- \edef\askedopened{#2}%
- \ifx\askednames\empty
- \edef\askednames{\getvalue{\??ih\v!content\c!list}}%
- \fi
- \ifx\askednames\empty
- \let\askednames\v!all
- \fi
- \ifthirdargument
- \getparameters[\??bm][#3]%
- \else\ifsecondargument
- \doifassignmentelse{#2}{\let\askedopened\empty\getparameters[\??bm][#2]}\donothing
- \fi\fi
- \ctxcommand{registerbookmark {
- names = "\askednames",
- opened = "\askedopened",
- force = "\bookmarkparameter\c!force",
- number = "\bookmarkparameter\c!number",
- }}%
- \endgroup
+ \expandafter\strc_bookmarks_place_yes
+ \else
+ \expandafter\gobblethreeoptionals
\fi}
-\setupbookmarks
- [\c!force=\v!no, % it's easier to force that to inhibit
- \c!number=\v!yes] % might become v!no
+\let\m_bookmarks_names \empty
+\let\m_bookmarks_opened\empty
+
+\def\strc_bookmarks_place_yes[#1][#2][#3]%
+ {\begingroup
+ \edef\m_bookmarks_names{#1}%
+ \edef\m_bookmarks_opened{#2}%
+ \ifx\m_bookmarks_names\empty
+ \edef\m_bookmarks_names{\namedlistparameter\v!content\c!list}%
+ \fi
+ \ifx\m_bookmarks_names\empty
+ \let\m_bookmarks_names\v!all
+ \fi
+ \ifthirdargument
+ \setupcurrentbookmark[#3]% no every so not all possible
+ \else\ifsecondargument
+ \doifassignmentelse{#2}{\let\m_bookmarks_opened\empty\setupcurrentbookmark[#2]}\donothing
+ \fi\fi
+ \ctxcommand{registerbookmark {
+ names = "\m_bookmarks_names",
+ opened = "\m_bookmarks_opened",
+ force = "\bookmarkparameter\c!force",
+ number = "\bookmarkparameter\c!number",
+ }}%
+ \endgroup}
\appendtoks
\ctxcommand{setupbookmarks {
@@ -107,7 +123,7 @@
stopper = \!!bs\bookmarkparameter\c!numberstopper\!!es,
segments = "\bookmarkparameter\c!numbersegments",
}}%
-\to \everysetupbookmarks
+\to \everysetupbookmark
\protect \endinput
diff --git a/tex/context/base/strc-blk.lua b/tex/context/base/strc-blk.lua
index d2f25dfb3..791f8f99b 100644
--- a/tex/context/base/strc-blk.lua
+++ b/tex/context/base/strc-blk.lua
@@ -9,10 +9,9 @@ if not modules then modules = { } end modules ['strc-blk'] = {
-- this one runs on top of buffers and structure
local type = type
-local gmatch, find = string.gmatch, string.find
-local lpegmatch = lpeg.match
+local find, format, validstring = string.find, string.format, string.valid
local settings_to_set, settings_to_array = utilities.parsers.settings_to_set, utilities.parsers.settings_to_array
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+local allocate = utilities.storage.allocate
local structures, context = structures, context
@@ -45,7 +44,7 @@ function blocks.print(name,data,hide)
else
context.dostartnormalblock(name)
end
- context.viafile(data)
+ context.viafile(data,format("block.%s",validstring(name,"noname")))
if hide then
context.dostophiddenblock()
else
diff --git a/tex/context/base/strc-blk.mkiv b/tex/context/base/strc-blk.mkiv
index 3bd5d04ed..1dd144aa9 100644
--- a/tex/context/base/strc-blk.mkiv
+++ b/tex/context/base/strc-blk.mkiv
@@ -22,92 +22,78 @@
% todo: prefix numbers (needs further integration elsewhere)
% check functionality
% alternative files (needs further integration elsewhere)
+%
+% order matters: \c!before (think of: \c!before=\startitemize)
+%
+% no \endgroups
-\def\namedblockparameter#1#2{\ifcsname\??tb#1#2\endcsname\csname\??tb#1#2\endcsname\fi}
-
-\unexpanded\def\setupblockparameters{\dodoubleargument \dosetupblock} % fast one (for compatibility)
-\unexpanded\def\setupblock {\dodoubleargumentwithset\dosetupblock} % handles set
-
-\def\dosetupblock[#1]{\getparameters[\??tb#1]} % [#1][#2]}
+\installcorenamespace {block}
+\installcorenamespace {blocktemp}
-\unexpanded\def\defineblock[#1]%
- {\processcommalist[#1]\dodefineblock}
+\installcommandhandler \??block {block} \??block
-\def\dodefineblock#1%
- {\getparameters
- [\??tb#1]
- [\c!before=\blank,
- \c!after=\blank,
- \c!inner=,
- \c!style=,
- \c!file=]% todo
- \ctxcommand{definestructureblock("#1")}%
- \setuvalue{\e!begin#1}{\dodoubleempty\dobeginofblock[#1]}%
- \letvalue{\e!end#1}\relax}
+\appendtoks
+ \ctxcommand{definestructureblock("\currentblock")}%
+ \setuevalue{\e!begin\currentblock}{\dodoubleempty\strc_blocks_begin[\currentblock]}%
+ \setuevalue{\e!end \currentblock}{}%
+\to \everydefineblock
-\def\dobeginofblock[#1][#2]%
+\unexpanded\def\strc_blocks_begin[#1][#2]%
{\normalexpanded{\buff_pickup{@block@}{\e!begin#1}{\e!end#1}}
{}% before
{\ctxcommand{savestructureblock("#1","#2","@block@")}}}% after
-\def\dostarthiddenblock
+\let\strc_blocks_setup\relax
+
+\unexpanded\def\dostarthiddenblock % called at lua end
{\startnointerference
\dostartnormalblock}
-\def\dostophiddenblock
+\unexpanded\def\dostophiddenblock % called at lua end
{\dostopnormalblock
\stopnointerference}
-% order matters: \c!before (think of: \c!before=\startitemize)
-
-% no \endgroups
-
-\let\doblocksetups\gobbleoneargument
-
-\def\dostartnormalblock#1% name
+\unexpanded\def\dostartnormalblock#1% called at lua end
{\bgroup
- \visibletrue
+ \visibletrue % will change
\edef\currentblock{#1}%
- \doblocksetups\currentblock
- \let\doblocksetups\gobbleoneargument
- \namedblockparameter\currentblock\c!before
- \dousestylehashparameter{\??tb\currentblock}\c!style
- \dousecolorhashparameter{\??tb\currentblock}\c!color
- \namedblockparameter\currentblock\c!inner
+ \strc_blocks_setup
+ \let\strc_blocks_setup\relax
+ \blockparameter\c!before
+ \useblockstyleandcolor\c!style\c!color % maybe moev one line up (font spacing)
+ \blockparameter\c!inner % better \c!setups
\ignorespaces}
-\def\dostopnormalblock
+\unexpanded\def\dostopnormalblock % called at lua end
{\removeunwantedspaces
- \namedblockparameter\currentblock\c!after
+ \blockparameter\c!after
\par % todo: alternative = text, paragraph
\egroup}
-\def\dosetblockstate[#1][#2][#3]% state name tag
+\def\strc_blocks_set_state[#1][#2][#3]% state name tag
{\ctxcommand{setstructureblockstate("#1","#2","#3")}}
-\def\doselectblocks[#1][#2][#3][#4]% state name tag setups
+\def\strc_blocks_select[#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]}%
- \ctxcommand{selectstructureblock("#1","#2","","\@@tb@@tbcriterium")}}
- {\getparameters[\??tb\??tb][\c!criterium=\v!text,#4]%
- \def\doblocksetups##1{\getparameters[\??tb##1][#4]}%
- \ctxcommand{selectstructureblock("#1","#2","#3","\@@tb@@tbcriterium")}}%
+ {\getparameters[\??blocktemp][\c!criterium=\v!text,#3]%
+ \def\strc_blocks_setup{\setupcurrentblock[#3]}%
+ \ctxcommand{selectstructureblock("#1","#2","","\csname\??blocktemp\c!criterium\endcsname")}}
+ {\getparameters[\??blocktemp][\c!criterium=\v!text,#4]%
+ \def\strc_blocks_setup{\setupcurrentblock[#4]}%
+ \ctxcommand{selectstructureblock("#1","#2","#3","\csname\??blocktemp\c!criterium\endcsname")}}%
\egroup}
-% hide: save, if [+] also hidden execute
-% keep: save and normal execute
-
-\def\hideblocks{\dotripleempty\dosetblockstate[hide]}
-\def\keepblocks{\dotripleempty\dosetblockstate[keep]}
-
+% hide : save, if [+] also hidden execute
+% keep : save and normal execute
% use : normal execute unless [-]
% process: hidden execute unless [-]
% select : idem use
-\def\useblocks {\doquadrupleempty\doselectblocks[use]}
-\def\processblocks{\doquadrupleempty\doselectblocks[process]}
-\def\selectblocks {\doquadrupleempty\doselectblocks[use]}
+\unexpanded\def\hideblocks {\dotripleempty \strc_blocks_set_state[hide]}
+\unexpanded\def\keepblocks {\dotripleempty \strc_blocks_set_state[keep]}
+\unexpanded\def\useblocks {\doquadrupleempty\strc_blocks_select [use]}
+\unexpanded\def\processblocks{\doquadrupleempty\strc_blocks_select [process]}
+\unexpanded\def\selectblocks {\doquadrupleempty\strc_blocks_select [use]}
\protect \endinput
diff --git a/tex/context/base/strc-con.mkvi b/tex/context/base/strc-con.mkvi
index 956acaae5..64371579a 100644
--- a/tex/context/base/strc-con.mkvi
+++ b/tex/context/base/strc-con.mkvi
@@ -27,17 +27,16 @@
%
% 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.
+%D Constructions are just descriptions but a bit more abstract so that we can
+%D conveniently build upon them. They are not really meant for users but module
+%D writers might find them useful. We mention a couple of parameters but these are
+%D only mentioned because in the shared code we map all resolvers to constructions.
+%D
+%D On top of constructions we build descriptions, enumerations, notes, labels and
+%D maybe some day more.
\unprotect
-\ifdefined\v!construction \else \def\v!construction{construction} \fi
-
%D Todo:
\installcorenamespace{construction}
@@ -70,9 +69,9 @@
%
\c!alternative=\v!left,
\c!display=\v!yes,
- \c!width=7em,
- \c!distance=1em,
- \c!titledistance=0.5em,
+ \c!width=7\emwidth,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
%c!hang=,
%c!sample=,
\c!margin=\v!no,
@@ -137,9 +136,9 @@
{\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.
+%D As we will build on top of the generic construction mechanism we have handlers
+%D as a sort of plug in mechanism. In order to have some consistency we share
+%D some namespaces.
\installcorenamespace{constructioninitializer}
\installcorenamespace{constructionfinalizer}
@@ -154,7 +153,7 @@
\unexpanded\def\strc_constructions_initialize#1% class instance
{\edef\currentconstruction{#1}%
-\let\currentconstructionlistentry\!!zerocount
+ \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
@@ -167,16 +166,16 @@
\newconditional\c_strc_constructions_number_state
\newconditional\c_strc_constructions_title_state
-\setvalue{\??constructioninitializer\v!construction}%
+\unexpanded\setvalue{\??constructioninitializer\v!construction}%
{\setfalse\c_strc_constructions_number_state
\setfalse\c_strc_constructions_title_state}
-\setvalue{\??constructionfinalizer\v!construction}%
+\unexpanded\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.
+%D We keep the command variant around but rather would move to the start-stop one.
+%D Also, passing the title as argument has some history so we need to keep that as
+%D well.
\ifdefined\dotagsetconstruction \else \let\dotagsetconstruction\relax \fi
@@ -190,10 +189,10 @@
\unexpanded\def\currentconstructionsample
{\begstrut
\constructionparameter\c!text
- \constructionparameter\c!sample
+ \p_strc_constructions_sample
\endstrut}
-\setvalue{\??constructionmainhandler\v!construction}#1%
+\unexpanded\setvalue{\??constructionmainhandler\v!construction}#1%
{\iftrialtypesetting \else
\begingroup
\currentconstructionsynchronize % reinstated
@@ -202,7 +201,7 @@
\endgroup
\fi#1}
-\setvalue{\??constructiontexthandler\v!construction}%
+\unexpanded\setvalue{\??constructiontexthandler\v!construction}%
{\begingroup
\useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext
\the\everyconstruction
@@ -224,36 +223,54 @@
\def\resetconstructions % to be used in e.g. footnotes
{\c_strc_constructions_nested_state\zerocount}
-\setvalue{\??constructioncommandhandler\v!construction}%
+\unexpanded\setvalue{\??constructioncommandhandler\v!construction}%
{\endgroup}
-\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing
+\let\p_strc_constructions_sample \empty
+\let\p_strc_constructions_align \empty
+\let\p_strc_constructions_indenting \empty
+\let\p_strc_constructions_width \empty
+\let\p_strc_constructions_aligntitle \empty
+\let\p_strc_constructions_renderingsetup\empty
+\let\p_strc_constructions_headalign \empty
+\let\p_strc_constructions_hang \empty
+\let\p_strc_constructions_inbetween \empty
+\let\p_strc_constructions_closesymbol \empty
+
+\unexpanded\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}%
% \checkconstructionalternativeparent % this catches an unknown alternative
- \doifnotsetups{\constructionalternativeparameter\c!renderingsetup}
+ \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}%
+ \doifnotsetups\p_strc_constructions_renderingsetup
{\letconstructionparameter\c!alternative\v!left
\let\currentconstructionalternative\v!left}%
\doadaptleftskip{\constructionparameter\c!margin}%
\setlocalhsize % so we can use \localhsize in width assignments
\constructionsheaddistance\constructionalternativeparameter\c!distance\relax
+ \edef\p_strc_constructions_width{\constructionalternativeparameter\c!width}%
\ifdim\constructionsheaddistance=\zeropoint
- \doif{\constructionalternativeparameter\c!width}\v!broad{\constructionsheaddistance\emwidth}%
+ \ifx\p_strc_constructions_width\v!broad
+ \constructionsheaddistance\emwidth
+ \fi
\fi
% inefficient and not always needed, for instance not with margins so we will make checkers
- % per alternative
+ % per alternative some day (especially in labels this is unwanted overhead)
\setbox\constructionheadbox\hbox
{\forgetall
\dontcomplain
\settrialtypesetting
- \doifelsenothing{\constructionparameter\c!sample}
- {\csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext}%
- {\csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructionsample}}%
+ \edef\p_strc_constructions_sample{\constructionparameter\c!sample}%
+ \ifx\p_strc_constructions_sample\empty
+ \csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext
+ \else
+ \csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructionsample
+ \fi}%
\assignwidth
- {\constructionalternativeparameter\c!width}
+ \p_strc_constructions_width
\constructionsheadwidth
{\unhcopy\constructionheadbox}
\constructionsheaddistance
@@ -266,15 +283,24 @@
\else
\csname\??constructionmainhandler\currentconstructionhandler\endcsname{\boxedconstructionhead\currentconstructiontext}%
\fi}%
- \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...
+ \edef\p_strc_constructions_aligntitle{\constructionparameter\c!aligntitle}%
+ \ifx\p_strc_constructions_aligntitle\v!no
+ \leftconstructionskip \leftskip
+ \rightconstructionskip\rightskip
+ \else
+ \ifcase\c_strc_constructions_nested_state
+ \leftconstructionskip \leftskip
+ \rightconstructionskip\rightskip
+ \fi
+ \fi
+ \edef\p_strc_constructions_align{\constructionparameter\c!align}%
+ \ifx\p_strc_constructions_align\empty \else
+ \setupalign[\p_strc_constructions_align]% \use...
+ \fi
+ \edef\p_strc_constructions_indenting{\constructionparameter\c!indenting}%
+ \ifx\p_strc_constructions_indenting\empty \else
+ \indenting[\p_strc_constructions_indenting]% \use...
+ \fi
\ifcase\c_strc_constructions_nested_state
\c_strc_constructions_nested_state\plusone
\or
@@ -282,15 +308,15 @@
\fi
\strc_constructions_close_symbol_reset
%
- % \doifnotsetups {\constructionalternativeparameter\c!renderingsetup}
- % {\let\currentconstructionalternative\v!left}%
- \directsetup{\constructionalternativeparameter\c!renderingsetup}\relax
+ \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}%
+ %
+ \directsetup\p_strc_constructions_renderingsetup\relax
%
\dostoptagged % tag
\dostarttagged\t!constructioncontent\empty
\ignorespaces} % args not needed
-\setvalue{\??constructionstophandler\v!construction}%
+\unexpanded\setvalue{\??constructionstophandler\v!construction}%
{\strc_constructions_close_symbol_place
\doifnot{\constructionparameter\c!display}\v!no\par
\dostoptagged % content
@@ -302,16 +328,21 @@
% \endgroup
\dorechecknextindentation}
-\def\boxedconstructionhead#1%
+\unexpanded\def\boxedconstructionhead#1%
{\vtop
{\hsize\constructionsheadwidth
- \doifsomething{\constructionparameter\c!headalign}{\setupalign[\constructionparameter\c!headalign]}%
+ \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}%
+ \ifx\p_strc_constructions_headalign\empty \else
+ \setupalign[\p_strc_constructions_headalign]% \use...
+ \fi
#1}}
\installcorenamespace{constructionalternative}
\installcorenamespace{constructionrenderings}
% see lists: alternativemethods ... todo
+%
+% there will be a proper interface to variables
\installcommandhandler \??constructionalternative {constructionalternative} \??constructionalternative
@@ -391,16 +422,15 @@
{\setbox\constructionheadbox\vtop % \vbox gaat fout in hang
{\forgetall
\dontcomplain
- \hsize\constructionsheadwidth
- \edef\p_headalign{\constructionparameter\c!headalign}%
- \ifx\p_headalign\empty
+ \hsize\constructionsheadwidth\relax
+ \ifx\p_strc_constructions_headalign\empty
\setupalign[#1]% use fast one
\else
- \setupalign[\p_headalign]% use fast one
+ \setupalign[\p_strc_constructions_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}%
-\setbox\constructionheadbox\hbox{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex
+ \setbox\constructionheadbox\hbox{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex
\ht\constructionheadbox\strutht
\dp\constructionheadbox\strutdp}
@@ -408,12 +438,11 @@
{\setbox\constructionheadbox\vtop
{\forgetall
\dontcomplain
- \hsize\constructionsheadwidth
- \edef\p_headalign{\constructionparameter\c!headalign}%
- \ifx\p_headalign\empty
+ \hsize\constructionsheadwidth\relax
+ \ifx\p_strc_constructions_headalign\empty
\setupalign[#1]% use fast one
\else
- \setupalign[\p_headalign]% use fast one
+ \setupalign[\p_strc_constructions_headalign]% use fast one
\fi
\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}%
\setbox\constructionheadbox\hbox{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex
@@ -421,18 +450,18 @@
\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
+ {\ifx\p_strc_constructions_hang\empty
+ % nothing
+ \else\ifx\p_strc_constructions_hang\v!fit
\scratchdimen\htdp\constructionheadbox
\getnoflines\scratchdimen
\hangafter-\noflines
- \else\ifx\p_hang\v!broad
+ \else\ifx\p_strc_constructions_hang\v!broad
\scratchdimen\dimexpr\htdp\constructionheadbox+.5\strutht\relax
\getnoflines\scratchdimen
\hangafter-\noflines
\else
- \hangafter-\p_hang
+ \hangafter-\p_strc_constructions_hang
\fi\fi\fi
\relax
\hangindent\ifx#1\v!right-\fi\constructionsheadwidth}
@@ -441,18 +470,18 @@
% 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}
+ \edef\p_strc_constructions_hang{\constructionparameter\c!hang}%
+ \doifsetupselse{\??constructionrenderings:\v!left:\p_strc_constructions_hang} {
+ \directsetup{\??constructionrenderings:\v!left:\p_strc_constructions_hang}
} {
\directsetup{\??constructionrenderings:\v!left:\v!hanging}
}
\stopsetups
\startsetups[\??constructionrenderings:\v!right]
- \edef\p_hang{\constructionparameter\c!hang}
- \doifsetupselse{\??constructionrenderings:\v!right:\p_hang} {
- \directsetup{\??constructionrenderings:\v!right:\p_hang}
+ \edef\p_strc_constructions_hang{\constructionparameter\c!hang}
+ \doifsetupselse{\??constructionrenderings:\v!right:\p_strc_constructions_hang} {
+ \directsetup{\??constructionrenderings:\v!right:\p_strc_constructions_hang}
} {
\directsetup{\??constructionrenderings:\v!right:\v!hanging}
}
@@ -462,9 +491,8 @@
\let\\=\crlf
\noindent
\strc_constructions_set_pure_box\v!flushleft
- \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth\relax
- \rightskip\rightconstructionskip
- \advance\leftskip\constructionsheaddistance
+ \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax
+ \rightskip\rightconstructionskip\relax
\llap {
\hbox to \leftskip {
\hskip\leftconstructionskip
@@ -573,13 +601,18 @@
\stopsetups
\startsetups[\??constructionrenderings:\v!top]
- \dohandlepagebreakX\plusone
+ \strc_sectioning_prevent_page_break\plusone
\let\\=\space
\noindent
- \copy\constructionheadbox\par % copy ?
- \nobreak
- \doifelsenothing{\constructionparameter\c!inbetween}{\blank}{\constructionparameter\c!inbetween}%
+ \copy\constructionheadbox % why copy ?
+ \par
\nobreak
+ \edef\p_strc_constructions_inbetween{\constructionparameter\c!inbetween}%
+ \ifx\p_strc_constructions_inbetween\empty \else
+ \p_strc_constructions_inbetween
+ \par
+ \nobreak
+ \fi
\useconstructionstyleandcolor\c!style\c!color
\ignorespaces
\stopsetups
@@ -639,9 +672,9 @@
\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}
+ \edef\p_strc_constructions_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace
+ \doifsetupselse{\??constructionrenderings:\v!serried:\p_strc_constructions_width} {
+ \directsetup{\??constructionrenderings:\v!serried:\p_strc_constructions_width}
} {
\directsetup{\??constructionrenderings:\v!serried:\v!wide}
}
@@ -687,7 +720,7 @@
\noindent
\advance\leftskip-\leftskipadaption\relax
\ifdim\leftskipadaption=\zeropoint
- \leftskipadaption1.5em\relax % just some default
+ \leftskipadaption1.5\emwidth\relax % just some default
\ifnum\c_strc_constructions_nested_state=\plusone
\ifdim\leftskip>\zeropoint \relax
\leftskipadaption\leftskip
@@ -699,7 +732,7 @@
\fi
\hskip-\leftskipadaption\relax
\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox
- \kern\ifdim\constructionsheaddistance=\zeropoint .75em\else\constructionsheaddistance\fi
+ \kern\ifdim\constructionsheaddistance=\zeropoint .75\emwidth\else\constructionsheaddistance\fi
\useconstructionstyleandcolor\c!style\c!color
\ignorespaces
\stopsetups
@@ -731,9 +764,9 @@
\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
+ \edef\p_strc_constructions_closesymbol{\constructionparameter\c!closesymbol}%
+ \ifx\p_strc_constructions_closesymbol\empty \else
+ \constructionparameter\c!closecommand{\p_strc_constructions_closesymbol}% hm why {} maybe because box expected
\fi
\fi}
diff --git a/tex/context/base/strc-def.mkiv b/tex/context/base/strc-def.mkiv
index 7917b7d83..0738bdf29 100644
--- a/tex/context/base/strc-def.mkiv
+++ b/tex/context/base/strc-def.mkiv
@@ -16,59 +16,6 @@
\unprotect
-\setupheads[%
- %\c!after=,
- %\c!align=,
- %\c!aligntitle=,
- \c!alternative=\v!normal,
- %\c!before=,
- %\c!color=,
- \c!command=\normalplacehead,
- \c!continue=\v!yes,
- %\c!coupling=,
- %\c!deepnumbercommand=,
- %\c!deeptextcommand=,
- %\c!default=,
- \c!distance=\!!zeropoint,
- \c!expansion=\v!no,
- %\c!file=,
- %\c!footer=,
- %\c!grid=,
- \c!hang=\v!none,
- %\c!header=,
- \c!incrementnumber=\v!yes,
- \c!indentnext=\v!no,
- %\c!label=,
- %\c!limittext=\languageparameter\c!limittext,
- \c!margin=\zeropoint,
- %\c!margintext=,
- \c!number=\v!yes,
- \c!numbercolor=\headparameter\c!color,
- \c!textcolor=\headparameter\c!color,
- \c!numberstyle=\headparameter\c!style,
- \c!textstyle=\headparameter\c!style,
- %\c!numbercommand=,
- %\c!textcommand=,
- \c!ownnumber=\v!no,
- %\c!page=,
- \c!placehead=\v!yes,
- \c!sectionconversionset=\s!default,
- \c!sectionnumber=\v!yes,
- %\c!sectionsegments=,
- \c!sectionseparatorset=\s!default,
- \c!sectionset=\v!all,
- \c!interlinespace=,
- %\c!sectionstopper=,
- %\c!sectionstarter=,
- %\c!strut=,
- %\c!style=,
- %\c!text=,
- %\c!tolerance=,
- %\c!beforesection=\directsetup{document:\currenthead:start}, % these might become defaults i.e. acpect document: namespace
- %\c!insidesection=\directsetup{document:\currenthead:inside}, % these might become defaults i.e. acpect document: namespace
- %\c!aftersection=\directsetup{document:\currenthead:stop}, % these might become defaults i.e. acpect document: namespace
- ]
-
% \setupsectionblock[appendix][sectionconversionset=appendix]
% \setuphead[chapter][sectionconversionset=\sectionblockparameter\c!sectionconversionset] % \sectionblockparameter]
@@ -102,7 +49,7 @@
% \startsetups defaults:frontpart:pagenumbers:roman
% \defineconversionset[\c!frontpart:\c!pagenumber][][romannumerals]
-% \setupuserpagenumber[\c!way=\v!byblock]
+% \setupuserpagenumber[\c!way=\v!by\v!block]
% \stopsetups
% \definesectionblock
@@ -233,7 +180,7 @@
\c!marking=\v!page,
\c!header=,
\c!style=\tfc,
- \c!distance=.75em,
+ \c!distance=.75\emwidth,
\c!before={\blank[2*\v!big]},
\c!after={\blank[2*\v!big]}]
@@ -242,7 +189,7 @@
[%\c!align=,
%\c!indentnext=\v!no,
\c!style=\tfa,
- \c!distance=.75em,
+ \c!distance=.75\emwidth,
\c!before={\blank[2*\v!big]},
\c!after=\blank]
diff --git a/tex/context/base/strc-des.mkii b/tex/context/base/strc-des.mkii
index 587ef13e7..e699df9ea 100644
--- a/tex/context/base/strc-des.mkii
+++ b/tex/context/base/strc-des.mkii
@@ -47,7 +47,7 @@
% Op die manier is meer mogelijk en worden \par's geskipt.
%
% De macro \??dd#1\s!do\c!commando levert de koppeling tussen
-% \doornumberen en \doordefinieren. Deze constructie is nodig
+% \doornummeren en \doordefinieren. Deze constructie is nodig
% omdat doornummeren geen argument heeft en omdat subnummers
% niet worden genest binnen het hogere niveau.
%
diff --git a/tex/context/base/strc-des.mkvi b/tex/context/base/strc-des.mkvi
index 29072fbc6..5635ff0df 100644
--- a/tex/context/base/strc-des.mkvi
+++ b/tex/context/base/strc-des.mkvi
@@ -33,9 +33,9 @@
%\c!color=,
%\c!headcolor=,
%\c!titlecolor=,
- \c!width=7em,
- \c!distance=1em,
- \c!titledistance=0.5em,
+ \c!width=7\emwidth,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
%\c!hang=,
%\c!sample=,
%\c!align=,
@@ -71,15 +71,17 @@
\setuevalue{\e!stop \currentdescription}{\strc_descriptions_stop}%
\to \everydefinedescription
-\setvalue{\??constructioninitializer\v!description}%
+\let\p_strc_constructions_title \empty
+
+\unexpanded\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
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
\settrue\c_strc_constructions_title_state
\else
\setfalse\c_strc_constructions_title_state
@@ -116,10 +118,6 @@
\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_titled[#1]%
{\doifnextbgroupelse
{\strc_descriptions_start_yes_titled_indeed[#1]}%
@@ -141,11 +139,6 @@
\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}
-% \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
-
\unexpanded\def\strc_descriptions_start_nop_titled
{\doifnextbgroupelse
{\strc_descriptions_start_nop_titled_indeed}%
@@ -203,10 +196,6 @@
\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_titled
{\doifnextbgroupelse
{\strc_descriptions_nop_titled_indeed}%
@@ -227,17 +216,36 @@
\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}%
+\unexpanded\setvalue{\??constructioncommandhandler\v!description}%
{\dowithpar
{\csname\??constructionstarthandler\v!construction\endcsname}%
{\csname\??constructionstophandler \v!construction\endcsname\endgroup}}
-\setvalue{\??constructionstarthandler\v!description}%
+\unexpanded\setvalue{\??constructionstarthandler\v!description}%
{\BeforePar{\csname\??constructionstarthandler\v!construction\endcsname}%
\GotoPar}
-\setvalue{\??constructionstophandler\v!description}%
+\unexpanded\setvalue{\??constructionstophandler\v!description}%
{\csname\??constructionstophandler\v!construction\endcsname
\endgroup}
+%D For historic reasons we have (from now on undocumented):
+
+\definedescription
+ [tab]
+ [\c!alternative=\v!left,
+ \c!headstyle=\v!normal,
+ \c!headcolor=,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!width=\v!broad,
+ \c!sample=\hskip4\emwidth,
+ \c!before=,
+ \c!after=]
+
+\unexpanded\def\setuptab
+ {\setupdescription[tab]}
+
+%D Maybe we should remove this definition.
+
\protect \endinput
diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua
index f10b175a4..98d69f4ce 100644
--- a/tex/context/base/strc-doc.lua
+++ b/tex/context/base/strc-doc.lua
@@ -22,7 +22,7 @@ local max, min = math.max, math.min
local allocate, mark, accesstable = utilities.storage.allocate, utilities.storage.mark, utilities.tables.accesstable
local catcodenumbers = catcodes.numbers
-local ctxcatcodes = tex.ctxcatcodes
+local ctxcatcodes = catcodenumbers.ctxcatcodes
local variables = interfaces.variables
local v_last = variables.last
@@ -64,7 +64,7 @@ local a_internal = attributes.private('internal')
local data
function documents.initialize()
- data = {
+ data = allocate { -- whole data is marked
numbers = { },
forced = { },
ownnumbers = { },
@@ -204,7 +204,7 @@ end
function sections.setblock(name)
local block = name or data.block or "unknown" -- can be used to set the default
data.block = block
- context(block)
+ return block
end
function sections.pushblock(name)
@@ -213,7 +213,7 @@ function sections.pushblock(name)
data.blocks[#data.blocks+1] = block
data.block = block
documents.reset()
- context(block)
+ return block
end
function sections.popblock()
@@ -221,7 +221,7 @@ function sections.popblock()
local block = data.blocks[#data.blocks] or data.block
data.block = block
documents.reset()
- context(block)
+ return block
end
function sections.currentblock()
@@ -253,7 +253,8 @@ function sections.somelevel(given)
-- normally these are passed as argument but nowadays we provide several
-- interfaces (we need this because we want to be compatible)
if trace_detail then
- report_structure("name '%s', mapped level '%s', old depth '%s', new depth '%s', reset set '%s'",givenname,mappedlevel,olddepth,newdepth,resetset)
+ report_structure("name '%s', mapped level '%s', old depth '%s', new depth '%s', reset set '%s'",
+ givenname, mappedlevel or "unknown", olddepth, newdepth, resetset)
end
local u = given.userdata
if u then
@@ -767,27 +768,31 @@ function sections.findnumber(depth,what) -- needs checking (looks wrong and slow
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
+ if s then
+ 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
- elseif #n < depth then
- break
end
end
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
+ if s then
+ 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
- elseif #n < depth then
- break
end
end
end
@@ -926,3 +931,10 @@ commands.structureautocatcodedget = function(name,catcode) sections.structured
commands.namedstructurevariable = function(depth,name) sections.structuredata(depth,name) end
commands.namedstructureuservariable = function(depth,name) sections.userdata (depth,name) end
+
+--
+
+function commands.setsectionblock (name) context(sections.setblock(name)) end
+function commands.pushsectionblock(name) context(sections.pushblock(name)) end
+function commands.popsectionblock () context(sections.popblock()) end
+
diff --git a/tex/context/base/strc-doc.mkiv b/tex/context/base/strc-doc.mkiv
index 4e9dec32e..c8dfae1e4 100644
--- a/tex/context/base/strc-doc.mkiv
+++ b/tex/context/base/strc-doc.mkiv
@@ -17,240 +17,10 @@
\unprotect
-\def\c!xmlsetup{xmlsetup}
+%D This will move:
-% We operate in a \type {@@ns} namespace. All data is passed through
-% variables. Of course we can built another interface on top of this
-% that accepts multiple arguments. We might change this approach and
-% remove this layer but it was needed for the transition.
-
-\installcorenamespace{structure}
-
-\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters
-
-% \definesystemvariable{ns}
-% \def\structureparameter#1{\csname\??ns#1\endcsname}
-% \def\detokenizedstructureparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??ns#1\endcsname}}
-
-\setupstructure % not a user command so we might need to change the name
- [\c!number=,
- \c!level=,
- \c!name=,
- \c!title=,
- \c!bookmark=,
- \c!marking=,
- \c!list=,
- \c!label=,
- \c!coupling=,
- \c!ownnumber=,
- \c!sectionseparatorset=\s!default,
- \c!sectionconversionset=\s!default,
- \c!sectionstopper=,
- \c!sectionstarter=,
- \c!sectionsegments=,
- \c!sectionresetset=,
- \c!reference=,
- \c!backreference=,
- \c!expansion=\v!no,
- \c!xmlsetup=,
- \s!catcodes=,
- \c!saveinlist=\v!yes,
- \c!command=\showstructuredata]
-
-% maybe flags for list, bm, mark
-
-\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
- \setupstructure[#1]%
- \xdef\currentstructurename {\structureparameter\c!name}%
- \xdef\currentstructurecoupling {\structureparameter\c!coupling}%
- \xdef\currentstructureownnumber {\structureparameter\c!ownnumber}% optional own number
- \xdef\currentstructurelevel {\structureparameter\c!level}%
- \edef\currentstructureexpansion {\structureparameter\c!expansion}%
- \xdef\currentstructurexmlsetup {\structureparameter\c!xmlsetup}%
- \xdef\currentstructurecatcodes {\structureparameter\s!catcodes}%
- \xdef\currentstructurelabel {\structureparameter\c!label}%
- \xdef\currentstructurereference {\structureparameter\c!reference}%
- \xdef\currentstructurereferenceprefix{\structureparameter\c!referenceprefix}%
- \xdef\currentstructurebackreference {\structureparameter\c!backreference}%
- \xdef\currentstructureshownumber {\structureparameter\c!number}%
- \xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}%
- \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}%
- \ifx\currentstructureexpansion\s!xml
- \xmlstartraw
- \xdef\currentstructuretitle {\structureparameter\c!title}%
- \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
- \xdef\currentstructuremarking {\structureparameter\c!marking}%
- \xdef\currentstructurelist {\structureparameter\c!list}%
- \xmlstopraw
- \ifx\currentstructurelist\empty
- \globallet\currentstructurelist\currentstructuretitle
- \fi
- \globallet\currentstructurecoding\s!xml
- \else
- \ifx\currentstructureexpansion\v!yes
- \xdef\currentstructuretitle {\structureparameter\c!title}%
- \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
- \xdef\currentstructuremarking {\structureparameter\c!marking}%
- \xdef\currentstructurelist {\structureparameter\c!list}%
- \else
- \xdef\currentstructuretitle {\detokenizedstructureparameter\c!title}%
- \xdef\currentstructurebookmark{\detokenizedstructureparameter\c!bookmark}%
- \xdef\currentstructuremarking {\detokenizedstructureparameter\c!marking}%
- \xdef\currentstructurelist {\detokenizedstructureparameter\c!list}%
- \iflocation \ifx\currentstructurebookmark\empty
- \begingroup
- \simplifycommands
- \xdef\currentstructurebookmark{\detokenize\expandafter{\normalexpanded{\structureparameter\c!title}}}%
- \endgroup
- \fi \fi
- \fi
- \ifx\currentstructurelist\empty
- \globallet\currentstructurelist\currentstructuretitle
- \fi
- \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 = "\currentsectionblock",
- reference = "\currentstructurereference",
- referenceprefix = "\currentstructurereferenceprefix",
- backreference = "\currentstructurebackreference",
- },
- directives = {
- resetset = "\structureparameter\c!sectionresetset",
- },
- metadata = {
- kind = "section",
- name = "\currentstructurename",
- catcodes = \the\ifx\currentstructurecatcodes\empty\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi,
- coding = "\currentstructurecoding",
- \ifx\currentstructurecoding\s!xml
- xmlroot = "\xmldocument",
- \fi
- \ifx\currentstructurexmlsetup\empty \else
- xmlsetup = "\currentstructurexmlsetup",
- \fi
- \ifx\currentstructuresaveinlist\v!no
- nolist = true,
- \fi
- \ifx\currentstructureincrementnumber\v!yes
- increment = "\currentstructureincrementnumber",
- \fi
- },
- titledata = { % we can add mark and reference
- label = \!!bs\detokenize\expandafter{\currentstructurelabel }\!!es,
- title = \!!bs\detokenize\expandafter{\currentstructuretitle }\!!es,
- \ifx\currentstructurebookmark\currentstructuretitle \else
- bookmark = \!!bs\detokenize\expandafter{\currentstructurebookmark }\!!es,
- \fi
- \ifx\currentstructuremarking\currentstructuretitle \else
- marking = \!!bs\detokenize\expandafter{\currentstructuremarking }\!!es,
- \fi
- \ifx\currentstructuresaveinlist\v!no \else
- \ifx\currentstructurelist\currentstructuretitle \else
- list = \!!bs\detokenize\expandafter{\currentstructurelist}\!!es,
- \fi
- \fi
- },
- numberdata = {
- % needed ?
- block = "\currentsectionblock",
- hidenumber = \ifx\currentstructureshownumber\v!no true\else nil\fi, % titles
- % so far
- separatorset = "\structureparameter\c!sectionseparatorset",
- conversion = "\structureparameter\c!sectionconversion", % for good old times sake
- conversionset = "\structureparameter\c!sectionconversionset",
- starter = \!!bs\structureparameter\c!sectionstarter\!!es,
- stopper = \!!bs\structureparameter\c!sectionstopper\!!es,
- set = "\structureparameter\c!sectionset",
- segments = "\structureparameter\c!sectionsegments",
- ownnumber = "\currentstructureownnumber",
- },
- userdata = \!!bs\detokenize{#2}\!!es % will be converted to table at the lua end
- }
- }}%
- \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\currentsectioncountervalue \!!zerocount % redefined later
-\let\previoussectioncountervalue\!!zerocount % redefined later
-
-% todo: a direct flusher (needed when hidden)
-
-\def\setstructuresynchronization#1% todo: use ctxcontext
+\unexpanded\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()}}
-
-% Beware: we need to flush the data to the list explicitly. This is because
-% node in inserted and we may want control over when that happens.
-
-\def\showstructuredata
- {\par
- \dontleavehmode\begingroup
- \currentstructuresynchronize
- \currentstructureattribute
- [\currentstructurename: \showstructurelevel: \currentstructuretitle]
- \endgroup\par}
-
-% We can access the (stored) data with the following macros.
-%
-% \def\MyHeadCommand #1#2{\framed{#1}\framed{#2 / \structureuservariable{subtitle}}}
-% \def\MyListCommand#1#2#3{\externalfigure[\structurelistuservariable{figure}][height=5mm]#2}
-%
-% \setuphead[chapter][command=\MyHeadCommand]
-% \setuplist[chapter][alternative=command,command=\MyListCommand]
-%
-% \starttext
-% \setupheadertexts[chapter]
-% \setupinteraction[state=start]
-% \placebookmarks[chapter]
-% \placelist[chapter]
-% \startchapter[ownnumber=10,title=Ton,list=Hans,marking=Kees,bookmark=Bram][figure=cow.pdf,subtitle=oeps]
-% \stopchapter
-% \stoptext
-
-% todo: #1 => "#1" ... adapt lua code for name and number
-
-\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/tex/context/base/strc-enu.mkvi b/tex/context/base/strc-enu.mkvi
index e3261fa35..7b3f04942 100644
--- a/tex/context/base/strc-enu.mkvi
+++ b/tex/context/base/strc-enu.mkvi
@@ -85,10 +85,10 @@
%\c!color=,
%\c!headcolor=,
%\c!titlecolor=,
- \c!width=8em,
- \c!distance=0pt,
-\c!distance=1em,
- \c!titledistance=0.5em,
+ \c!width=8\emwidth,
+ \c!distance=\zeropoint,
+ \c!distance=\emwidth,
+ \c!titledistance=.5\emwidth,
%\c!hang=,
%\c!sample=,
%\c!align=,
@@ -175,15 +175,18 @@
\strc_enumerations_setup_counter\currentenumeration
\to \everydefineenumeration
-\setvalue{\??constructioninitializer\v!enumeration}%
+\let\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\unexpanded\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
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
\settrue\c_strc_constructions_number_state
\iftrialtypesetting
\strc_counters_save\currentconstructionnumber
@@ -192,14 +195,14 @@
\else
\setfalse\c_strc_constructions_number_state
\fi
- \edef\p_title{\constructionparameter\c!title}%
- \ifx\p_title\v!yes
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
\settrue\c_strc_constructions_title_state
\else
\setfalse\c_strc_constructions_title_state
\fi}
-\setvalue{\??constructionfinalizer\v!enumeration}%
+\unexpanded\setvalue{\??constructionfinalizer\v!enumeration}%
{\ifconditional\c_strc_constructions_number_state
\iftrialtypesetting
\strc_counters_restore\currentconstructionnumber
@@ -218,7 +221,8 @@
%D Counters (maybe we can share this code): (not ok yet, messy with notes)
-%%%%%%%%%%% BEGIN TODO (SEE NOTES) %%%%%%%%%%%%%%%
+% Maybe we should move counters to the construction level as more derived mechanisms
+% use it \unknown\ so don't depend on names here!
\newtoks\everysetupenumerationcounter
@@ -236,18 +240,15 @@
\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
+ \ifx\currentenumeration\empty \else
+ \strc_enumerations_setup_counter\currentenumeration
+ \fi
\to \everysetupenumeration
-%%%%%%%%%%% END TODO (SEE NOTES) %%%%%%%%%%%%%%%
-
%D Initializer:
%D The handlers.
@@ -263,7 +264,7 @@
\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}%
+\unexpanded\setvalue{\??constructiontexthandler\v!enumeration}%
{\begingroup
\useconstructionstyleandcolor\c!headstyle\c!headcolor
\strc_enumerations_text
@@ -363,23 +364,23 @@
%
% 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")}}
+% to do / to be checked
+
+\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}
+
+\unexpanded\def\strc_enumerations_skip_number_coupling[#1]% e.g. for questions with no answer
+ {\ctxlua{structures.references.setnextorder("construction","#1")}}
\protect \endinput
diff --git a/tex/context/base/strc-flt.mkvi b/tex/context/base/strc-flt.mkvi
index 05cfa40e3..07013b292 100644
--- a/tex/context/base/strc-flt.mkvi
+++ b/tex/context/base/strc-flt.mkvi
@@ -23,8 +23,10 @@
%
% todo: strc_floats_analyze_variables_two could trigger a setup
% and we could have nofmethods of them
-
-% Less globals!
+%
+% todo: move variables from page-flt to strc-flt
+%
+% todo: less globals!
%D This module is being converted into a mkvi one.
%D
@@ -44,7 +46,7 @@
\let\setupcaption \setupfloatcaption
\let\setupcaptions\setupfloatcaption
-\def\dohandlenextfloatindent
+\unexpanded\def\dohandlenextfloatindent
{\useindentnextparameter\floatparameter
\dorechecknextindentation}
@@ -118,7 +120,7 @@
\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!margin=1\emwidth,
\c!method=1,
\c!cache=\v!yes, % when no, then intermediate flush
\c!leftmargin=\zeropoint, % displacement in 'normal floats'
@@ -129,7 +131,7 @@
\c!rightmargindistance=\floatparameter\c!leftmargindistance,
\c!ntop=2,
\c!nbottom=0,
- \c!nlines=4,
+ \c!nlines=4, % used?
%\c!local=,
%\c!bottombefore=, % e.g. \vfill
%\c!bottomafter=,
@@ -144,45 +146,44 @@
\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
+\let\strc_floats_define_saved\definefloat
\unexpanded\def\definefloat
- {\dotripleempty\dodefinefloat}
+ {\dotripleempty\strc_floats_define}
-\def\dodefinefloat[#1][#2][#3]% #1=naam #2=meervoud #3=parent
+\def\strc_floats_define[#1][#2][#3]% #1=naam #2=meervoud #3=parent
{\ifthirdargument
- \redodefinefloat[#1][#2][#3]%
+ \strc_floats_define_cloned[#1][#2][#3]%
\else\ifsecondargument
- \dododefinefloat[#1][#2]%
+ \strc_floats_define_normal[#1][#2]%
\else
- \dododefinefloat[#1][#1]%
+ \strc_floats_define_normal[#1][#1]%
\fi\fi}
-\def\dododefinefloat[#1][#2]%
+\def\strc_floats_define_normal[#1][#2]%
{\definefloatcaption[#1]%
\definecounter[#1]%
\definelist[#1]%
\presetlabeltext[#1=\Word{#1}~]%
\presetheadtext[#2=\Word{#2}]%
- \saveddefinefloat[#1]%
- \dodefinefloatcommands[#1][#2]}
+ \strc_floats_define_saved[#1]%
+ \strc_floats_define_commands{#1}{#2}}
-\def\redodefinefloat[#1][#2][#3]%
+\def\strc_floats_define_cloned[#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]}
+ \strc_floats_define_saved[#1][#3]%
+ \strc_floats_define_commands{#1}{#2}}
-\def\dodefinefloatcommands[#1][#2]%
+\def\strc_floats_define_commands#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}}%
@@ -254,11 +255,11 @@
% begin of todo
-\unexpanded\def\placefloatcaption{\dodoubleempty\doplacefloatcaption}
-\unexpanded\def\setfloatcaption {\dodoubleempty\dodosetfloatcaption}
+\unexpanded\def\placefloatcaption{\dodoubleempty\strc_floats_place_caption}
+\unexpanded\def\setfloatcaption {\dodoubleempty\strc_floats_set_caption}
-\def\doplacefloatcaption[#tag][#reference]#caption{[not supported]}
-\def\dodosetfloatcaption[#tag][#reference]#caption{[not supported]} % \dosetfloatcaption already in use
+\def\strc_floats_place_caption[#tag][#reference]#caption{[not supported]}
+\def\strc_floats_set_caption [#tag][#reference]#caption{[not supported]}
\unexpanded\def\placefloatcaptiontext [#tag]{[not suported yet]}
\unexpanded\def\placefloatcaptionnumber [#tag]{[not suported yet]}
@@ -441,11 +442,15 @@
% we're really dealing with the float. Some day I'll root out
% the global settings.
+\let\lastplacedfloat\empty
+
\def\strc_floats_set_current_tag#tag%
{\edef\currentfloat{#tag}%
\ifx\currentfloat\empty
\let\currentfloat\v!figure % a bit of a hack
\fi
+ \global\let\lastplacedfloat\currentfloat
+ \let\m_strc_floats_saved_userdata\empty
\let\currentfloatcaption\currentfloat}
\def\strc_floats_reset_variables
@@ -483,22 +488,36 @@
% start-stop
+% \startplacefigure[title=oeps][subtitle=whatever]
+% \framed[width=10cm,height=5cm]{\floatuserdataparameter{subtitle}}
+% \stopplacefigure
+
+\installcorenamespace{floatuserdata}
+
+\installsetuponlycommandhandler \??floatuserdata {floatuserdata}
+
+\let\m_strc_floats_saved_userdata\empty % todo: reset this in non start|stop cases
+
\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}
+ \dodoubleempty\strc_floats_start_place_indeed}
-\def\strc_floats_start_place_indeed[#settings]% tricky ... saved not ok yet
+\def\strc_floats_start_place_indeed[#settings][#userdata]%
{\strc_floats_reset_variables
\edef\savedfloatlocation{\floatcaptionparameter\c!location}%
\setupcurrentfloatcaption[\c!location=,\c!reference=,\c!title=,\c!marking=,\c!list=,\c!bookmark=,#settings]%
+ \def\m_strc_floats_saved_userdata{#2}%
\edef\floatlocation{\floatcaptionparameter\c!location}%
\setupcurrentfloatcaption[\c!location=\savedfloatlocation]%
\ifx\floatlocation\empty
\edef\floatlocation{\floatparameter\c!default}%
\fi
+ \ifsecondargument
+ \setupcurrentfloatuserdata[#userdata]%
+ \fi
\doifinsetelse\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal
\bgroup
\ignorespaces}
@@ -569,15 +588,18 @@
% 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}
+\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
+%setnewconstant\c_page_one_float_method \zerocount % 0=raw 1=safe (.99) 2=tight (-1pt) / belongs in page-one
+\setnewconstant\c_strc_floats_rotation \zerocount % 0 90 180 270
+\newconditional\c_strc_floats_par_float
+
\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
@@ -595,7 +617,7 @@
\splitfloat{\strc_floats_place_next_box_normal}}
\unexpanded\def\strc_floats_place_next_box_normal
- {\ifsomefloatwaiting
+ {\ifconditional\c_page_floats_some_waiting
% this was \checkwaitingfloats spread all over
\doifinsetelse\v!always\floatlocation
{\showmessage\m!floatblocks5\empty}
@@ -628,63 +650,58 @@
\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
+ \global\d_page_sides_downshift \zeropoint
+ \global\d_page_sides_extrashift\zeropoint
+ \ifconditional\c_strc_floats_par_float
\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
+ \global\setfalse\c_strc_floats_par_float
\else
- \doifcommonelse
- {\floatlocation}
- {\flushfloatslist}
- {\global\parfloattrue}
- {\global\parfloatfalse}%
+ \doifcommonelse\floatlocation\flushfloatslist
+ {\global\settrue \c_strc_floats_par_float}
+ {\global\setfalse\c_strc_floats_par_float}%
\fi
- \global\sidefloatshift\zeropoint
- \global\sidefloatmaximum\zeropoint
- \global\sidefloatmethod\floatparameter\c!sidemethod
- \global\textfloatmethod\floatparameter\c!textmethod
- \global\sidefloatalign\zerocount
- \global\floatrotation\zerocount
+ \global\d_page_sides_shift \zeropoint
+ \global\d_page_sides_maximum \zeropoint
+ \global\c_page_sides_method \floatparameter\c!sidemethod
+ \global\c_page_one_float_method \floatparameter\c!textmethod
+ \global\c_page_sides_align \zerocount
+ \global\c_strc_floats_rotation \zerocount
\strc_floats_calculate_skips
- \ifparfloat
+ \ifconditional\c_strc_floats_par_float
\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'
+ [\v!height=>\global\c_page_sides_align\plusone ,%
+ \v!line=>\global\c_page_sides_align\plustwo ,% (***)
+ \v!depth=>\global\c_page_sides_align\plusthree,%
+ \v!grid=>\global\c_page_sides_align\plusfour ,%
+ \v!halfline=>\global\c_page_sides_align\plusfive ]%
+ \ifcase\c_page_sides_align\relax % todo: optie v!lokaal => \else
+ \doifinset\v!height \floatlocation{\global\c_page_sides_align\plusone }%
+ \doifinset\v!line \floatlocation{\global\c_page_sides_align\plustwo }%
+ \doifinset\v!depth \floatlocation{\global\c_page_sides_align\plusthree}%
+ \doifinset\v!grid \floatlocation{\global\c_page_sides_align\plusfour }%
+ \doifinset\v!halfline\floatlocation{\global\c_page_sides_align\plusfive }% meant for 'none'
\fi
- \doifinset\v!high\floatlocation{\global\sidefloattopskip \zeropoint}%
- \doifinset\v!low \floatlocation{\global\sidefloatbottomskip\zeropoint}%
+ \doifinset\v!high\floatlocation{\global\d_page_sides_topskip \zeropoint}%
+ \doifinset\v!low \floatlocation{\global\d_page_sides_bottomskip\zeropoint}%
\doifinset\v!fit \floatlocation
- {\global\sidefloattopskip \zeropoint
- \global\sidefloatbottomskip\zeropoint
- \global\floatsideskip \zeropoint}%
+ {\global\d_page_sides_topskip \zeropoint
+ \global\d_page_sides_bottomskip\zeropoint
+ \global\d_strc_floats_margin \zeropoint}%
\else
\processallactionsinset
[\floatlocation]
- [ 90=>\global\floatrotation\commalistelement\relax,%
- 180=>\global\floatrotation\commalistelement\relax,%
- 270=>\global\floatrotation\commalistelement\relax]%
+ [ 90=>\global\c_strc_floats_rotation\commalistelement\relax,%
+ 180=>\global\c_strc_floats_rotation\commalistelement\relax,%
+ 270=>\global\c_strc_floats_rotation\commalistelement\relax]%
\fi
\doifinsetelse\v!nonumber\floatlocation
{\global\nofloatnumbertrue}
@@ -703,19 +720,15 @@
% documenteren in details
\def\strc_floats_analyze_variables_one
- {\doifelse{\floatparameter\c!local}\v!yes % fout keyword
- \globalcenterfloatboxtrue
- \globalcenterfloatboxfalse
- \ifglobalcenterfloatbox
- \localcenterfloatboxtrue
+ {\doifelse{\floatparameter\c!local}\v!yes\settrue\setfalse\c_page_floats_center_box_global % fout keyword
+ \ifconditional\c_page_floats_center_box_global
+ \settrue\c_page_floats_center_box_local
\else
- \doifinsetelse\v!local\floatlocation
- \localcenterfloatboxtrue
- \localcenterfloatboxfalse
+ \doifinsetelse\v!local\floatlocation\settrue\setfalse\c_page_floats_center_box_local
\fi
\doifnotcommon{\v!always,\v!here,\v!force}\floatlocation % ! ! ! ! ! !
- {\globalcenterfloatboxfalse
- \localcenterfloatboxfalse}}
+ {\setfalse\c_page_floats_center_box_global
+ \setfalse\c_page_floats_center_box_local}}
\let\naturalfloatheight\!!zeropoint
\let\naturalfloatwidth \!!zeropoint
@@ -762,6 +775,9 @@
\newconditional\usesamefloatnumber
\def\strc_floats_place_packaged_boxes
+ {\expandafter\strc_floats_place_packaged_boxes_indeed\expandafter{\m_strc_floats_saved_userdata}}
+
+\def\strc_floats_place_packaged_boxes_indeed#userdata%
{\bgroup
\ifconditional\usesamefloatnumber
\globallet\currentfloatnumber \previousfloatnumber
@@ -784,7 +800,7 @@
\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]%
- []%
+ [#userdata]%
\globallet\previousfloatnumber \m_strc_counters_last_registered_index
\globallet\currentfloatnumber \m_strc_counters_last_registered_index
\globallet\currentfloatattribute \m_strc_counters_last_registered_attribute
@@ -816,21 +832,11 @@
\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
+ {\ifconditional\c_page_floats_center_box_local
% also available check here?
\seteffectivehsize
\hsize\localhsize
@@ -878,18 +884,18 @@
% watch out: line alone aligns on the line ! ! !
\unexpanded\def\movesidefloat[#settings]% (-)n*line|x=,y=
- {\global\sidefloatdownshift \zeropoint
- \global\sidefloatextrashift\zeropoint
+ {\global\d_page_sides_downshift \zeropoint
+ \global\d_page_sides_extrashift\zeropoint
\doifassignmentelse{#settings}%
{\begingroup
\setupcurrentfloat[\c!x=\zeropoint,\c!y=\zeropoint,#settings]%
\ifgridsnapping
\getnoflines{\floatparameter\c!y}%
- \global\sidefloatdownshift\noflines\lineheight
+ \global\d_page_sides_downshift\noflines\lineheight
\else
- \global\sidefloatdownshift\floatparameter\c!y
+ \global\d_page_sides_downshift\floatparameter\c!y
\fi
- \global\sidefloatextrashift\floatparameter\c!x
+ \global\d_page_sides_extrashift\floatparameter\c!x
\endgroup}
{\movedownsidefloat[#settings]}}
@@ -909,17 +915,17 @@
\def\strc_floats_move_down_line#sign%
{\if!!donea \else
- \global\sidefloatdownshift\zeropoint
+ \global\d_page_sides_downshift\zeropoint
\!!doneatrue
\fi
- \global\advance\sidefloatdownshift#sign\lineheight}
+ \global\advance\d_page_sides_downshift#sign\lineheight}
\def\strc_floats_move_down_hang#lines%
{\if!!doneb \else
- \global\sidefloatsidelines\zerocount
+ \global\c_page_sides_n_of_lines\zerocount
\!!donebtrue
\fi
- \global\advance\sidefloatsidelines#lines\relax}
+ \global\advance\c_page_sides_n_of_lines#lines\relax}
\unexpanded\def\movedownsidefloat[#settings]% already in core
{\doifnotinstring{:}{#settings}
@@ -930,7 +936,7 @@
\endgroup}}
\unexpanded\def\hangsidefloat[#number]%
- {\global\sidefloatsidelines#number\relax}
+ {\global\c_page_sides_n_of_lines#number\relax}
\def\strc_floats_set_extra_action#rightpagelocation#leftpagelocation%
{\rightorleftpageaction
@@ -956,7 +962,7 @@
\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
+ % \d_page_sides_downshift will be reset afterwards, and can
% already be set at this point
\processcommacommand[\floatlocation]\strc_floats_check_extra_actions_step
\ifx\extrafloatlocation\empty \else
@@ -971,11 +977,11 @@
% 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\d_page_sides_shift \zeropoint % duplicate
+ \global\d_page_sides_maximum\zeropoint\relax % duplicate
+ \ifdim\d_page_sides_downshift=\zeropoint\else
\global\setbox\floatbox\vbox
- {\vskip\sidefloatdownshift
+ {\vskip\d_page_sides_downshift
\nointerlineskip
\box\floatbox}%
\fi
@@ -1002,7 +1008,7 @@
\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}
+ {\global\d_page_sides_maximum\scratchwidth}
{\doifcommonelse{\v!right,\v!left}\floatlocation
\strc_floats_realign_floatbox_horizontal_one
\strc_floats_realign_floatbox_horizontal_two}%
@@ -1024,20 +1030,9 @@
\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
+\newdimen\d_strc_floats_margin
+\newdimen\d_strc_floats_top
+\newdimen\d_strc_floats_bottom
\def\strc_floats_calculate_skip#target#skip%
{\edef\askedfloatskip{#skip}%
@@ -1052,33 +1047,21 @@
\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
+ \strc_floats_calculate_skip\d_strc_floats_top {\rootfloatparameter\c!spacebefore }%
+ \strc_floats_calculate_skip\d_strc_floats_bottom {\rootfloatparameter\c!spaceafter }%
+ \strc_floats_calculate_skip\d_page_sides_topskip {\rootfloatparameter\c!sidespacebefore}%
+ \strc_floats_calculate_skip\d_page_sides_bottomskip{\rootfloatparameter\c!sidespaceafter }%
+ \global\d_strc_floats_margin \rootfloatparameter\c!margin
+ \global\d_page_sided_leftshift \floatparameter \c!leftmargindistance
+ \global\d_page_sided_rightshift\floatparameter \c!rightmargindistance
+ \global\c_page_floats_n_of_top \rootfloatparameter\c!ntop
+ \global\c_page_floats_n_of_bottom \rootfloatparameter\c!nbottom
\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
+\unexpanded\def\betweenfloatblanko % assumes that spaceafter is present
{\blank[\rootfloatparameter\c!spacebefore]} % or v!back,....
-\def\doplacefloatbox % used elsewhere
+\unexpanded\def\doplacefloatbox % used elsewhere
{%\forgetall % NO
\whitespace
\blank[\rootfloatparameter\c!spacebefore]
@@ -1096,20 +1079,16 @@
\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
+ \global\floatwidth \wd\floatbox
+ \global\floatheight \ht\floatbox % forget about the depth
+ \global\floattextwidth\dimexpr\hsize-\floatwidth-\rootfloatparameter\c!margin\relax
\edef\floatlocation{\floatlocationmethod}% to be sure .. why
\doifinsetelse\v!tall\floatlocationmethod
- {\floattextheight\pagegoal
- \advance\floattextheight -\pagetotal
- \advance\floattextheight -\bigskipamount % lelijk
+ {\floattextheight\dimexpr\pagegoal-\pagetotal-\bigskipamount\relax % ugly, this bigskip
\ifdim\floattextheight>\textheight
\floattextheight\textheight
\fi
- \boxmaxdepth\zeropoint \relax % toegevoegd
+ \boxmaxdepth\zeropoint\relax % toegevoegd
\ifdim\floattextheight<\floatheight
\floattextheight\floatheight
\fi
@@ -1126,11 +1105,7 @@
\def\strc_floats_stop_text_indeed
{\egroup
\doifnotinset\v!tall\floatlocation
- {\ifdim\ht\floattext<\floatheight
- \floattextheight\floatheight
- \else
- \floattextheight\ht\floattext
- \fi}%
+ {\floattextheight\ifdim\ht\floattext<\floatheight\floatheight\else\ht\floattext\fi}%
\setbox\floatbox\vbox to \floattextheight
{\hsize\floatwidth
\doifinsetelse\v!both\floatlocation
@@ -1171,7 +1146,7 @@
\dostoptagged
\blank[\rootfloatparameter\c!spaceafter]%
\strc_floats_end_text_group
- \doinsertfloatinfo}
+ \page_floats_report_total}
\def\borderedfloatbox
{\begingroup
@@ -1197,11 +1172,16 @@
\alignedline{\floatparameter\c!location}\v!middle}
\newdimen\d_strc_floats_content
+\newdimen\d_strc_float_temp_height
+\newdimen\d_strc_float_temp_width
+
+\def\captionminwidth {15\bodyfontsize}
+\def\captionovershoot{2\emwidth}
\def\strc_floats_set_page_variant
{\bgroup
\strc_floats_set_local_hsize
- \ifcase\floatrotation\else
+ \ifcase\c_strc_floats_rotation\else
\swapdimens\hsize\vsize
\fi
\forgetall
@@ -1211,10 +1191,12 @@
\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
+ \d_strc_floats_content\wd\b_strc_floats_content
\ifcase\floatparameter\c!method
- \or % automatic
- \ifnofloatcaption
+ % nothing
+ \or
+ % automatic
+ \ifnofloatcaption
\strc_floats_prepare_no_caption
%\page_backgrounds_add_local_to_box\floatbox % was \doglobal but not needed
\else
@@ -1227,21 +1209,20 @@
%\page_backgrounds_add_local_to_box\b_strc_floats_caption
\strc_floats_build_box
\fi
- \or % semi automatic
- \or % manual
+ \or
+ % semi automatic
+ \or
+ % manual
\fi
- \ifcase\floatrotation
+ \ifcase\c_strc_floats_rotation
\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}}%
+ {\rotate[\c!rotation=\number\c_strc_floats_rotation]{\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
@@ -1250,86 +1231,54 @@
\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}
+ {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}%
+ \edef\p_strc_floats_caption_width {\floatcaptionparameter\c!width}%
+ \edef\p_strc_floats_caption_minwidth{\floatcaptionparameter\c!minwidth}%
+ \edef\p_strc_floats_caption_align {\floatcaptionparameter\c!align}%
+ \dostarttagged\t!floatcaption\empty
+ \ifx\p_strc_floats_caption_location\v!top
+ \strc_floats_prepare_page_caption_top_bottom
+ \else\ifx\p_strc_floats_caption_location\v!bottom
+ \strc_floats_prepare_page_caption_top_bottom
+ \else\ifx\p_strc_floats_caption_width\v!fit
+ \strc_floats_prepare_side_auto_caption
+ \else\ifx\p_strc_floats_caption_width\v!max
+ \strc_floats_prepare_side_auto_caption
+ \else
+ \strc_floats_prepare_side_width_caption
+ \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_prepare_page_caption_top_bottom
+ {\ifx\p_strc_floats_caption_width\v!fit
+ \strc_floats_prepare_page_caption_top_bottom_fit_max
+ \else\ifx\p_strc_floats_caption_width\v!max
+ \strc_floats_prepare_page_caption_top_bottom_fit_max
+ \else
+ \strc_floats_prepare_side_width_caption % new, special effects (see icare)
+ \fi\fi}
+
+\def\strc_floats_prepare_page_caption_top_bottom_fit_max
+ {\ifx\p_strc_floats_caption_minwidth\v!fit
+ \ifx\p_strc_floats_caption_width\v!max
+ \strc_floats_prepare_stack_caption_max
+ \else\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content % wider caption
+ \ifx\p_strc_floats_caption_width\v!fit
+ \strc_floats_prepare_stack_caption_auto
+ \else
+ \strc_floats_prepare_stack_caption_width
+ \fi
+ \else
+ \strc_floats_prepare_stack_caption_min
+ \fi\fi
+ \else
+ \strc_floats_prepare_stack_caption_fixed
+ \fi}
\def\strc_floats_caption_set_align
- {\normalexpanded{\setupalign[\v!reset,\floatcaptionparameter\c!align]}}
+ {\normalexpanded{\setupalign[\v!reset,\p_strc_floats_caption_align]}}
-\def\dopreparesideautocaption
+\def\strc_floats_prepare_side_auto_caption
{\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
@@ -1341,41 +1290,43 @@
\hsize\scratchdimen
\strc_floats_make_complete_caption}}
-\def\dopreparesidewidthcaption
+\def\strc_floats_prepare_side_width_caption
{\setbox\b_strc_floats_caption\vbox
{\strc_floats_caption_set_align
\hsize\floatcaptionparameter\c!width
\strc_floats_make_complete_caption}}
-\def\dopreparestackcaptionfix
+\def\strc_floats_prepare_stack_caption_fixed
{\setbox\b_strc_floats_caption\vbox
{\strc_floats_caption_set_align
\hsize\floatcaptionparameter\c!minwidth % special effects
\strc_floats_make_complete_caption}}
-\def\dopreparestackcaptionmax
+\def\strc_floats_prepare_stack_caption_max
{\setbox\b_strc_floats_caption\vbox
{\strc_floats_caption_set_align
\hsize\wd\b_strc_floats_content
\strc_floats_make_complete_caption}}
-\def\dopreparestackcaptionwid
+\def\strc_floats_prepare_stack_caption_width
{\setbox\b_strc_floats_caption\vbox
{\strc_floats_caption_set_align
\hsize\floatcaptionparameter\c!width
\strc_floats_make_complete_caption}}
-\def\dopreparestackcaptionmin
+\def\strc_floats_prepare_stack_caption_min
{\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 !
+ \ifx\p_strc_floats_caption_align\empty
+ \raggedcenter % on purpose overloads align !
+ \fi
\strc_floats_make_complete_caption}}
-\def\dopreparestackcaptionaut
- {\doifsomething{\floatcaptionparameter\c!align}
- {\doifnotinset\v!middle{\floatcaptionparameter\c!align}%
- {\let\captionovershoot\!!zeropoint}}%
+\def\strc_floats_prepare_stack_caption_auto
+ {\ifx\p_strc_floats_caption_align\empty \else
+ \doifnotinset\v!middle\p_strc_floats_caption_align{\let\captionovershoot\!!zeropoint}%
+ \fi
\edef\captionhsize{\the\wd\b_strc_floats_content}%
\ifdim\captionhsize>\hsize
% float is wider than \hsize
@@ -1388,8 +1339,7 @@
\ifdim\ht\scratchbox>\lineheight % more lines
\setbox\b_strc_floats_caption\vbox
{\strc_floats_caption_set_align
- \hsize\captionhsize
- \advance\hsize -\captionovershoot\relax
+ \hsize\dimexpr\captionhsize-\captionovershoot\relax
\ifdim\hsize<\captionminwidth\relax
\hsize\captionhsize
\fi
@@ -1408,175 +1358,192 @@
\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
+ \scratchdimen\dimexpr\captionhsize+\captionovershoot+3\emwidth\relax % 3em is 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
+ \scratchdimen\dimexpr\captionhsize+\captionovershoot\relax
+ \ifdim\scratchdimen<\hsize
+ \hsize\scratchdimen
+ \fi
+ \strc_floats_make_complete_caption}%
+ \else\ifx\p_strc_floats_caption_align\empty
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\captionhsize
+ \raggedcenter % overloads
\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
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\captionhsize
+ \strc_floats_make_complete_caption}%
+ \fi\fi
\fi}
-\newdimen\tempfloatheight
-\newdimen\tempfloatwidth
+\def\strc_floats_between_stack
+ {\endgraf
+ \nointerlineskip
+ \floatcaptionparameter\c!inbetween
+ \endgraf}
-\def\dofloatboxbetweenstack
- {\endgraf\nointerlineskip\floatcaptionparameter\c!inbetween\endgraf}
-
-\def\dofloatboxdefaultbuilder % done
+\def\strc_floats_build_box_default % 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
+\def\strc_floats_build_box_next_right#1%
+ {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi
+ {\d_strc_float_temp_height\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}}%
+ \doifnotinset\v!hang{\floatcaptionparameter\c!location}
+ {\dotfskip{\floatcaptionparameter\c!distance}}%
+ \vbox to\d_strc_float_temp_height{#1}}}
+
+\def\strc_floats_build_box_next_left#1%
+ {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi
+ {\d_strc_float_temp_height\ht\b_strc_floats_content
+ \vbox to\d_strc_float_temp_height{#1}%
+ \doifnotinset\v!hang{\floatcaptionparameter\c!location}
+ {\dotfskip{\floatcaptionparameter\c!distance}}%
\box\b_strc_floats_content}}
-\def\dofloatboxnextouterbuilder
- {\doifrightpagefloatelse\dofloatboxnextrightbuilder\dofloatboxnextleftbuilder}
+\def\strc_floats_build_box_next_outer
+ {\doifrightpagefloatelse\strc_floats_build_box_next_right\strc_floats_build_box_next_left}
-\def\dofloatboxnextinnerbuilder
- {\doifrightpagefloatelse\dofloatboxnextleftbuilder\dofloatboxnextrightbuilder}
+\def\strc_floats_build_box_next_inner
+ {\doifrightpagefloatelse\strc_floats_build_box_next_left\strc_floats_build_box_next_right}
-\def\dofloatboxnextrighthangbuilder#1%
- {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi
- {\tempfloatheight\ht\b_strc_floats_content
+\def\strc_floats_build_box_next_right_hang#1%
+ {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi
+ {\d_strc_float_temp_height\ht\b_strc_floats_content
\box\b_strc_floats_content
- \vbox to\tempfloatheight{#1}}}
+ \vbox to\d_strc_float_temp_height{#1}}}
-\def\dofloatboxnextlefthangbuilder#1%
- {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi
- {\tempfloatheight\ht\b_strc_floats_content
- \vbox to\tempfloatheight{#1}%
+\def\strc_floats_build_box_next_left_hang#1%
+ {\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi
+ {\d_strc_float_temp_height\ht\b_strc_floats_content
+ \vbox to\d_strc_float_temp_height{#1}%
\box\b_strc_floats_content}}
-\def\dodofloatboxnextrightmarginbuilder#1#2%
- {\ifparfloat
+\def\strc_floats_build_box_next_right_margin_indeed#1#2%
+ {\ifconditional\c_strc_floats_par_float
\hbox\bgroup
- \tempfloatheight\ht\b_strc_floats_content
+ \d_strc_float_temp_height\ht\b_strc_floats_content
\box\b_strc_floats_content
- \hsmash{\hskip#1\vbox to\tempfloatheight{#2}}%
+ \hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}%
\egroup
\else
\begingroup
- \tempfloatheight\ht\b_strc_floats_content
- \everyrightofalignedline{\hsmash{\hskip#1\vbox to\tempfloatheight{#2}}}%
+ \d_strc_float_temp_height\ht\b_strc_floats_content
+ \everyrightofalignedline{\hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}}%
\strc_floats_align_content{\box\b_strc_floats_content}%
\endgroup
\fi}
-\def\dodofloatboxnextleftmarginbuilder#1#2%
- {\ifparfloat
+\def\strc_floats_build_box_next_left_margin_indeed#1#2%
+ {\ifconditional\c_strc_floats_par_float
\hbox\bgroup
- \tempfloatheight\ht\b_strc_floats_content
- \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\tempfloatheight{#2}}%
+ \d_strc_float_temp_height\ht\b_strc_floats_content
+ \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#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}}}%
+ \d_strc_float_temp_height\ht\b_strc_floats_content
+ \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#2}}}%
\strc_floats_align_content{\box\b_strc_floats_content}%
\endgroup
\fi}
-\def\dofloatboxnextrightmarginbuilder{\dodofloatboxnextrightmarginbuilder\rightmargindistance}
-\def\dofloatboxnextleftmarginbuilder {\dodofloatboxnextleftmarginbuilder \leftmargindistance }
+\def\strc_floats_build_box_next_right_margin
+ {\strc_floats_build_box_next_right_margin_indeed\rightmargindistance}
+
+\def\strc_floats_build_box_next_left_margin
+ {\strc_floats_build_box_next_left_margin_indeed \leftmargindistance }
-\def\dofloatboxnextoutermarginbuilder
+\def\strc_floats_build_box_next_outer_margin
{\doifrightpagefloatelse
- {\dodofloatboxnextrightmarginbuilder\rightmargindistance}
- {\dodofloatboxnextleftmarginbuilder \rightmargindistance}}
+ {\strc_floats_build_box_next_right_margin_indeed\rightmargindistance}
+ {\strc_floats_build_box_next_left_margin_indeed \rightmargindistance}}
-\def\dofloatboxnextinnermarginbuilder
+\def\strc_floats_build_box_next_inner_margin
{\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]%
+ {\strc_floats_build_box_next_left_margin_indeed \leftmargindistance}
+ {\strc_floats_build_box_next_right_margin_indeed\leftmargindistance}}
+
+\def\strc_floats_build_box_next % beware, we first check on left/rightmargin because there can be left/right also
+ {\let\next\strc_floats_build_box_next_left
+ \processallactionsinset[\floatcaptionparameter\c!location]
+ [ \v!outermargin=>\let\next\strc_floats_build_box_next_outer_margin,
+ \v!innermargin=>\let\next\strc_floats_build_box_next_inner_margin,
+ \v!leftmargin=>\let\next\strc_floats_build_box_next_left_margin,
+ \v!rightmargin=>\let\next\strc_floats_build_box_next_right_margin,
+ \v!lefthanging=>\let\next\strc_floats_build_box_next_left_hang,
+ \v!righthanging=>\let\next\strc_floats_build_box_next_right_hang,
+ \v!outer=>\let\next\strc_floats_build_box_next_outer,
+ \v!inner=>\let\next\strc_floats_build_box_next_inner,
+ \v!left=>\let\next\strc_floats_build_box_next_left,
+ \v!right=>\let\next\strc_floats_build_box_next_right]%
\next}
-\def\dofloatboxsidebuilder
- {\ifparfloat
- \let\next\dofloatboxhighbuilder
+\def\strc_floats_build_box_side
+ {\ifconditional\c_strc_floats_par_float
+ \let\next\strc_floats_build_box_high
\else
- \let\next\dofloatboxmiddlebuilder
- \expanded{\processallactionsinset[\floatcaptionparameter\c!location]}
- [ \v!low=>\let\next\dofloatboxlowbuilder,
- \v!middle=>\let\next\dofloatboxmiddlebuilder,
- \v!high=>\let\next\dofloatboxhighbuilder]%
+ \let\next\strc_floats_build_box_middle
+ \processallactionsinset[\floatcaptionparameter\c!location]
+ [ \v!low=>\let\next\strc_floats_build_box_low,
+ \v!middle=>\let\next\strc_floats_build_box_middle,
+ \v!high=>\let\next\strc_floats_build_box_high]%
\fi
\next}
-\def\doflushfloatleftcaptionhang
- {\hsmash{\llap{\box\b_strc_floats_caption\dotfskip{\floatcaptionparameter\c!distance}}}}
-
-\def\doflushfloatrightcaptionhang
+\def\strc_floats_flush_right_caption_hang
{\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}}}
+\def\strc_floats_flush_left_caption_hang
+ {\hsmash{\llap{\box\b_strc_floats_caption\dotfskip{\floatcaptionparameter\c!distance}}}}
+
+% \def\strc_floats_flush_caption_hang % expanded can go
+% {\expanded{\doifinsetelse{\v!righthanging}{\floatcaptionparameter\c!location}}
+% {\strc_floats_flush_right_caption_hang}
+% {\expanded{\doifinsetelse{\v!lefthanging}{\floatcaptionparameter\c!location}}
+% {\strc_floats_flush_left_caption_hang}
+% {\expanded{\doifinsetelse{\v!hang}{\floatcaptionparameter\c!location}}
+% {\expanded{\doifinsetelse{\v!outer}{\floatcaptionparameter\c!location}}
+% {\doifrightpagefloatelse{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}}
+% {\expanded{\doifinsetelse{\v!right}{\floatcaptiondirectives}}
+% {\strc_floats_flush_right_caption_hang}
+% {\strc_floats_flush_left_caption_hang}}}
+% {\box\b_strc_floats_caption}}}}
+
+\def\strc_floats_flush_caption_hang % expanded can go
+ {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}%
+ \doifinsetelse\v!righthanging\p_strc_floats_caption_location
+ {\strc_floats_flush_right_caption_hang}
+ {\doifinsetelse\v!lefthanging\p_strc_floats_caption_location
+ {\strc_floats_flush_left_caption_hang}
+ {\doifinsetelse\v!hang\p_strc_floats_caption_location
+ {\doifinsetelse\v!outer\p_strc_floats_caption_location
+ {\doifrightpagefloatelse{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}}
+ {\doifinsetelse\v!right\floatcaptiondirectives
+ {\strc_floats_flush_right_caption_hang}
+ {\strc_floats_flush_left_caption_hang}}}
{\box\b_strc_floats_caption}}}}
-\def\dofloatboxhighbuilder
- {\dofloatboxnextbuilder{\dofloatboxbetweenstack\doflushfloatcaptionhang\vfill}}
+\def\strc_floats_build_box_high
+ {\strc_floats_build_box_next{\strc_floats_between_stack\strc_floats_flush_caption_hang\vfill}}
-\def\dofloatboxlowbuilder
- {\dofloatboxnextbuilder{\vfill\doflushfloatcaptionhang\dofloatboxbetweenstack}}
+\def\strc_floats_build_box_low
+ {\strc_floats_build_box_next{\vfill\strc_floats_flush_caption_hang\strc_floats_between_stack}}
-\def\dofloatboxmiddlebuilder
- {\dofloatboxnextbuilder{\vfill\box\b_strc_floats_caption\vfill}}
+\def\strc_floats_build_box_middle
+ {\strc_floats_build_box_next{\vfill\box\b_strc_floats_caption\vfill}}
% \definefloat
% [lefty][lefties][figure]
@@ -1594,125 +1561,136 @@
% \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\strc_floats_build_box_top_stack_normal_overlay
+ {\vbox to \ht\b_strc_floats_content{\vss\strc_floats_build_box_top_stack_normal_content}}
-\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\strc_floats_build_box_top_stack_normal_content
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
+ \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
+ \strc_floats_between_stack
+ \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}}
+ \strc_floats_between_stack
+ \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\strc_floats_build_box_bottom_stack_normal_overlay
+ {\vbox to \ht\b_strc_floats_content{\strc_floats_build_box_bottom_stack_normal_content\vss}}
+
+\def\strc_floats_build_box_bottom_stack_normal_content
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
+ \hbox{\hbox{\box\b_strc_floats_content}}%
+ \strc_floats_between_stack
+ \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}}%
+ \strc_floats_between_stack
+ \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}%
+ \fi}
+
+\def\strc_floats_build_box_top_stack_normal
+ {\doifinsetelse\v!overlay{\floatcaptionparameter\c!location}
+ \strc_floats_build_box_top_stack_normal_overlay
+ \strc_floats_build_box_top_stack_normal_content}
+
+\def\strc_floats_build_box_bottom_stack_normal
+ {\doifinset\v!overlay{\floatcaptionparameter\c!location}
+ \strc_floats_build_box_bottom_stack_normal_overlay
+ \strc_floats_build_box_bottom_stack_normal_content}
-\def\dofloatboxgridtopstackbuilder
+\def\strc_floats_build_box_top_stack_grid
{\dp\b_strc_floats_caption\strutdepth
\setbox\scratchbox\vbox
- {\tempfloatwidth\wd\b_strc_floats_content
- \ifparfloat
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
\strc_floats_locate_side_float{\box\b_strc_floats_caption}%
- \vss\dofloatboxbetweenstack
+ \vss\strc_floats_between_stack
\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_between_stack
\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
+\def\strc_floats_build_box_bottom_stack_grid
{\dp\b_strc_floats_caption\strutdepth
\setbox\scratchbox\vbox
- {\tempfloatwidth\wd\b_strc_floats_content
- \ifparfloat
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
\hbox{\box\b_strc_floats_content}%
- \vss\dofloatboxbetweenstack
+ \vss\strc_floats_between_stack
\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_between_stack
\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
+\def\strc_floats_build_box_top_stack_stretch
{\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
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
\strc_floats_locate_side_float{\box\b_strc_floats_caption}%
- \vss\dofloatboxbetweenstack\vss
+ \vss\strc_floats_between_stack\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
+ \vss\strc_floats_between_stack\vss
\strc_floats_align_content{\box\b_strc_floats_content}%
\fi}}
-\def\dofloatboxstretchbotstackbuilder
+\def\strc_floats_build_box_bottom_stack_stretch
{\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
+ {\d_strc_float_temp_width\wd\b_strc_floats_content
+ \ifconditional\c_strc_floats_par_float
\hbox{\box\b_strc_floats_content}%
- \vss\dofloatboxbetweenstack\vss
+ \vss\strc_floats_between_stack\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
+ \vss\strc_floats_between_stack\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]%
+\def\strc_floats_build_box_top
+ {\let\next\strc_floats_build_box_top_stack_normal
+ \processfirstactioninset[\floatcaptionparameter\c!location]
+ [ \v!grid=>\let\next\strc_floats_build_box_top_stack_grid,
+ \v!stretch=>\let\next\strc_floats_build_box_top_stack_stretch]%
\next}
-\def\dofloatboxbottombuilder
- {\let\next\dofloatboxnormalbotstackbuilder
- \expanded{\processfirstactioninset[\floatcaptionparameter\c!location]}
- [ \v!grid=>\let\next\dofloatboxgridstackbuilder,
- \v!stretch=>\let\next\dofloatboxstretchstackbuilder]%
+\def\strc_floats_build_box_bottom
+ {\let\next\strc_floats_build_box_bottom_stack_normal
+ \processfirstactioninset[\floatcaptionparameter\c!location]
+ [ \v!grid=>\let\next\strc_floats_build_box_bottom_stack_grid,
+ \v!stretch=>\let\next\strc_floats_build_box_bottom_stack_stretch]%
\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}}}
+\def\strc_floats_relocate_caption_right#1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{\hss#1}}}
+\def\strc_floats_relocate_caption_left #1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{#1\hss}}}
\unexpanded\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}}
@@ -1721,31 +1699,32 @@
{\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
+ \processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step
\executeifdefined{\??floatbuilder\floatcaptionarrangement}{\getvalue{\??floatbuilder\s!default}}}}
+\def\strc_floats_build_box_step#1%
+ {\doifdefined{\??floatbuilder#1}{\def\floatcaptionarrangement{#1}\quitcommalist}}
+
\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 }]%
+ \processallactionsinset[\floatcaptionparameter\c!location]
+ [ \v!left=>\let\next\strc_floats_relocate_caption_left,
+ \v!right=>\let\next\strc_floats_relocate_caption_right,
+ \v!inner=>\doifrightpagefloatelse{\let\next\strc_floats_relocate_caption_left }{\let\next\strc_floats_relocate_caption_right},
+ \v!outer=>\doifrightpagefloatelse{\let\next\strc_floats_relocate_caption_right}{\let\next\strc_floats_relocate_caption_left }]%
\next}
-\installfloatboxbuilder \v!none \dofloatboxdefaultbuilder
-\installfloatboxbuilder \s!default \dofloatboxdefaultbuilder
-\installfloatboxbuilder \v!high \dofloatboxhighbuilder
-\installfloatboxbuilder \v!low \dofloatboxlowbuilder
-\installfloatboxbuilder \v!middle \dofloatboxmiddlebuilder
+\installfloatboxbuilder \v!none \strc_floats_build_box_default
+\installfloatboxbuilder \s!default \strc_floats_build_box_default
+\installfloatboxbuilder \v!high \strc_floats_build_box_high
+\installfloatboxbuilder \v!low \strc_floats_build_box_low
+\installfloatboxbuilder \v!middle \strc_floats_build_box_middle
-\installfloatboxbuilder \v!left \dofloatboxsidebuilder
-\installfloatboxbuilder \v!right \dofloatboxsidebuilder
+\installfloatboxbuilder \v!left \strc_floats_build_box_side
+\installfloatboxbuilder \v!right \strc_floats_build_box_side
-\installfloatboxbuilder \v!top \dofloatboxtopbuilder
-\installfloatboxbuilder \v!bottom \dofloatboxbottombuilder
+\installfloatboxbuilder \v!top \strc_floats_build_box_top
+\installfloatboxbuilder \v!bottom \strc_floats_build_box_bottom
% \setuplayout[grid=yes] \showgrid \setupcaptions[style=smallbodyfont,location=grid,inbetween=]
%
@@ -1756,6 +1735,8 @@
% test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
% \stoptext
+% This might move to page-flt:
+
\newif\ifpostponecolumnfloats \postponecolumnfloatsfalse % don't change
\setnewconstant\postcenterfloatmethod\plusone
@@ -1774,9 +1755,9 @@
\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
+ {\ifconditional\c_page_floats_center_box_global
\donetrue
- \else\iflocalcenterfloatbox
+ \else\ifconditional\c_page_floats_center_box_local
\donetrue
\else
\donefalse
@@ -1793,7 +1774,6 @@
\forgetall
\postponenotes
\dontcomplain
- %\showcomposition
\setbox\b_strc_floats_content\vbox{\borderedfloatbox}%
%\page_backgrounds_add_local_to_box\b_strc_floats_content
\ifnofloatcaption
@@ -1808,33 +1788,106 @@
\fi
\egroup}
+% \def\strc_floats_prepare_side_caption
+% {\dostarttagged\t!floatcaption\empty
+% \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}%
+% \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_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}}}%
+ \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}%
+ \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}%
+ \ifx\p_strc_floats_caption_width\v!max
+ \strc_floats_prepare_side_caption_max
+ \else\ifx\p_strc_floats_caption_width\v!fit
+ \strc_floats_prepare_side_caption_fit
+ \else
+ \strc_floats_prepare_side_caption_width
+ \fi\fi
\dostoptagged}
+% these could be \??floatpreparesidecaption
+
+\def\strc_floats_prepare_side_caption_max
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}}
+
+\def\strc_floats_prepare_side_caption_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}
+
+\def\strc_floats_prepare_side_caption_width
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\p_strc_floats_caption_width % \wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}}
+
+% % maybe (but then also prepare_page that way):
+%
+% \installcorenamespace{floatpreparesidecaption}
+%
+% \def\strc_floats_prepare_side_caption
+% {\dostarttagged\t!floatcaption\empty
+% \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}%
+% \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}%
+% \expandcheckedcsname\??floatpreparesidecaption\p_strc_floats_caption_width\s!unknown
+% \dostoptagged}
+%
+% \setvalue{\??floatpreparesidecaption\v!max}%
+% {\setbox\b_strc_floats_caption\vbox
+% {\strc_floats_caption_set_align
+% \hsize\wd\b_strc_floats_content
+% \strc_floats_make_complete_caption}}
+%
+% \setvalue{\??floatpreparesidecaption\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}
+%
+% \setvalue{\??floatpreparesidecaption\s!unknown}%
+% {\setbox\b_strc_floats_caption\vbox
+% {\strc_floats_caption_set_align
+% \hsize\p_strc_floats_caption_width % \wd\b_strc_floats_content
+% \strc_floats_make_complete_caption}}
+
\def\strc_floats_locate_side_float#1%
{\begingroup
\alignstrutmode\zerocount
- \hsize\tempfloatwidth \forgetall
+ \hsize\d_strc_float_temp_width \forgetall
\alignedline{\floatparameter\c!location}\v!middle{#1}%
\endgroup}
@@ -1843,13 +1896,11 @@
\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
+ \ifconditional\c_strc_floats_par_float
\strc_floats_set_paragraph_variant
\else
\strc_floats_set_page_variant
@@ -1872,9 +1923,7 @@
\fi
\fi}
-\newcounter\noxfloatlocations
-
-% \def\dooutput{\sidefloatoutput} % redefinition of \dooutput
+% \def\dooutput{\sidefloatoutput} % redefinition of \dooutput
\definefloat
[\v!figure]
@@ -1900,17 +1949,17 @@
\installcorenamespace{floatmethods}
-\let\floatmethod \empty
-\let\floatlabel \empty
-\let\floatcolumn \empty
-\let\floatrow \empty
-\let\forcedfloatmethod\empty
+\let\floatmethod \empty % set by lua
+\let\floatlabel \empty % set by lua
+\let\floatcolumn \empty % set by lua
+\let\floatrow \empty % set by lua
+\let\forcedfloatmethod\empty % set by lua
\def\setfloatmethodvariables#1% \floatmethod \floatlabel \floatrow \floatcolumn
{\ctxcommand{analysefloatmethod("#1")}}
\def\somesomewherefloat[#1]%
- {\dofloatssavesomewherefloat\s!somewhere{#1}}
+ {\page_floats_save_somewhere_float\s!somewhere{#1}}
\def\strc_floats_get_box
{\ifvisible
@@ -2073,45 +2122,49 @@
%D Local floats:
-\def\setuplocalfloats
- {\getparameters[\??lf]}
+\installcorenamespace{localfloats}
+\installcorenamespace{localfloatstack}
+
+\installsetuponlycommandhandler \??localfloats {localfloats}
\setuplocalfloats
[%\c!before=\blank,
%\c!after=\blank,
\c!inbetween=\blank]
-\initializeboxstack{localfloats}
+\initializeboxstack\??localfloatstack
-\newcounter\noflocalfloats
+\newcount\c_strc_localfloats_n \let\noflocalfloats\c_strc_localfloats_n
-\def\resetlocalfloats
- {\doglobal\newcounter\noflocalfloats
- \initializeboxstack{localfloats}}
+\unexpanded\def\resetlocalfloats
+ {\global\c_strc_localfloats_n\zerocount
+ \initializeboxstack\??localfloatstack}
-\def\somelocalfloat
- {\doglobal\increment\noflocalfloats
- \savebox{localfloats}{\noflocalfloats}{\box\floatbox}}
+\unexpanded\def\somelocalfloat
+ {\global\advance\c_strc_localfloats_n\plusone
+ \savebox\??localfloatstack{\number\c_strc_localfloats_n}{\box\floatbox}}
-\def\getlocalfloats
- {\dorecurse\noflocalfloats
+\unexpanded\def\getlocalfloats
+ {\dorecurse\c_strc_localfloats_n
{\ifnum\recurselevel=\plusone % 1\relax
- \getvalue{\??lf\c!before}%
+ \directlocalfloatsparameter\c!before
\else
- \getvalue{\??lf\c!inbetween}%
+ \directlocalfloatsparameter\c!inbetween
\fi
- \dontleavehmode\hbox{\foundbox{localfloats}\recurselevel}%
- \ifnum\recurselevel=\noflocalfloats\relax
- \getvalue{\??lf\c!after}%
+ \dontleavehmode\hbox{\foundbox\??localfloatstack\recurselevel}%
+ \ifnum\recurselevel=\c_strc_localfloats_n\relax
+ \directlocalfloatsparameter\c!after
\fi}}
-\def\flushlocalfloats
+\unexpanded\def\flushlocalfloats
{\getlocalfloats
\resetlocalfloats}
-\unexpanded\def\getlocalfloat#1{\expanded{\foundbox{localfloats}{\number#1}}}
+\unexpanded\def\getlocalfloat#1%
+ {\normalexpanded{\foundbox{\??localfloatstack}{\number#1}}}
-\def\forcelocalfloats{\let\forcedfloatmethod\v!local}
+\unexpanded\def\forcelocalfloats
+ {\let\forcedfloatmethod\v!local}
\installfloatmethod \s!singlecolumn \v!local \somelocalfloat
\installfloatmethod \s!multicolumn \v!local \somelocalfloat
diff --git a/tex/context/base/strc-ind.mkiv b/tex/context/base/strc-ind.mkiv
index 4b65c7407..0098bff7d 100644
--- a/tex/context/base/strc-ind.mkiv
+++ b/tex/context/base/strc-ind.mkiv
@@ -57,6 +57,7 @@
\newcount\c_strc_indentedtexts_nesting
\newdimen\d_strc_indentedtexts_width
+\newdimen\d_strc_indentedtexts_distance
\appendtoks
\setuevalue {\e!start\currentindentedtext}{\strc_indentedtexts_start{\currentindentedtext}\c_strc_indentedtexts_nesting}%
@@ -67,12 +68,13 @@
\setuevalue{\v!sub\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{2}}%
\to \everydefineindentedtext
-\unexpanded\def\strc_indentedtexts_start#1#2%
+\unexpanded\def\strc_indentedtexts_start#1#2% we need to get rid of \spr
{\par
\begingroup
- \c_strc_indentedtexts_nesting#2\relax
\edef\currentindentedtext{#1}%
+ \c_strc_indentedtexts_nesting#2\relax
\indentedtextparameter\c!before
+ \d_strc_indentedtexts_distance\indentedtextparameter\c!distance\relax
\doifnothing{\indentedtextparameter\c!sample}
{\setindentedtextparameter\c!sample{\indentedtextparameter\c!text}}%
\assignwidth
@@ -81,15 +83,15 @@
{\useindentedtextstyleandcolor\c!headstyle\c!headcolor
\indentedtextparameter\c!sample
\spr{\indentedtextparameter\c!separator}}
- {\indentedtextparameter\c!distance}%
- \advance\d_strc_indentedtexts_width \indentedtextparameter\c!distance
+ {\d_strc_indentedtexts_distance}%
+ \advance\d_strc_indentedtexts_width \d_strc_indentedtexts_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}%
+ \hskip\d_strc_indentedtexts_distance}%
\parindent\zeropoint
\hskip\c_strc_indentedtexts_nesting\d_strc_indentedtexts_width
\advance\c_strc_indentedtexts_nesting\plusone
diff --git a/tex/context/base/strc-ini.lua b/tex/context/base/strc-ini.lua
index 78efcad81..3f0a8768f 100644
--- a/tex/context/base/strc-ini.lua
+++ b/tex/context/base/strc-ini.lua
@@ -27,10 +27,17 @@ 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 = tex.ctxcatcodes
-local xmlcatcodes = tex.xmlcatcodes
-local notcatcodes = tex.notcatcodes
-local txtcatcodes = tex.txtcatcodes
+local catcodenumbers = catcodes.numbers -- better use the context(...) way to switch
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local xmlcatcodes = catcodenumbers.xmlcatcodes
+local notcatcodes = catcodenumbers.notcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+
+local context, commands = context, commands
+
+local pushcatcodes = context.pushcatcodes
+local popcatcodes = context.popcatcodes
local trace_processors = false
local report_processors = logs.reporter("processors","structure")
@@ -226,7 +233,15 @@ end
if trace_processors then
report_processors("cct: %s, txt: %s",catcodes,title)
end
- context.sprint(catcodes,title) -- was: texsprint(catcodes,title)
+ --
+ -- context.sprint(catcodes,title)
+ --
+ -- doesn't work when a newline is in there \section{Test\ A} so we do
+ -- it this way:
+ --
+ pushcatcodes(catcodes)
+ context(title)
+ popcatcodes()
end
end
else
diff --git a/tex/context/base/strc-itm.mkvi b/tex/context/base/strc-itm.mkvi
index 86acba33c..da81f37d5 100644
--- a/tex/context/base/strc-itm.mkvi
+++ b/tex/context/base/strc-itm.mkvi
@@ -182,6 +182,7 @@
\newconditional\c_strc_itemgroups_columns
\newconditional\c_strc_itemgroups_concat
\newconditional\c_strc_itemgroups_txt
+\newconditional\c_strc_itemgroups_extra
\newconditional\c_strc_itemgroups_repeat
% 0 = before/after
@@ -242,11 +243,17 @@
\strc_itemgroups_insert_reference_indeed
\fi \fi}
+\def\strc_itemgroups_insert_extra_reference
+ {\iftrialtypesetting \else \ifx\currentitemreference \empty \else
+ \normalexpanded{\textreference[\currentitemreference]{\strc_itemgroups_extra_symbol}}%
+ \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",
+ % this is somewhat over the top ... we should use the counter's reference
+ \ctxcommand{setreferenceattribute("\s!full", "\referenceprefix","\currentitemreference",
{
metadata = {
kind = "item",% ?
@@ -360,7 +367,7 @@
\def\strc_itemgroups_insert_break_indeed {\flushnotes
\vspacing[\v!item @-5]}
\def\strc_itemgroups_insert_nobreak_indeed {\flushnotes
- \ifinsidecolumns
+ \ifinsidecolumns % todo
\vspacing[\v!item @5]%
\else
\vspacing[\v!item @500]%
@@ -452,6 +459,7 @@
% this will be a constant
\setfalse\c_strc_itemgroups_head
\setfalse\c_strc_itemgroups_sub
+ \setfalse\c_strc_itemgroups_symbol
\setfalse\c_strc_itemgroups_columns
% to be checked
\let\m_strc_itemgroups_destination\empty
@@ -584,9 +592,11 @@
{\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}
+ {\ifconditional\c_strc_itemgroups_sub \else
+ \ifconditional\c_strc_itemgroups_symbol \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
@@ -832,9 +842,6 @@
\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
@@ -873,16 +880,31 @@
\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]}
+\ifdefined\strc_itemgroups_start_columns
-\def\strc_itemgroups_stop_columns
- {\stopcolumns}
+ % already defined in page-mix
+
+\else
+
+ % will be redefined in page-mix
+
+ \ifdefined\startcolumns \else
+ \unexpanded\def\startcolumns[#settings]{}
+ \unexpanded\def\stopcolumns {}
+ \fi
+
+ \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}
+
+\fi
\unexpanded\def\stopitemgroup
{\stopcollectitems
@@ -1090,6 +1112,7 @@
\unexpanded\def\strc_itemgroups_start_symbol#text%
{\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
\startitemgroupitem}
\unexpanded\def\strc_itemgroups_start_dummy
@@ -1117,6 +1140,7 @@
\unexpanded\def\strc_itemgroups_start_text#text%
{\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
\settrue\c_strc_itemgroups_txt
\startitemgroupitem}
@@ -1219,29 +1243,33 @@
\unexpanded\def\strc_itemgroups_start_head_sym#text%
{\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_symbol
\settrue\c_strc_itemgroups_head
\strc_itemgroups_start_head}
\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
+ \ifconditional\c_strc_itemgroups_symbol
+ \strc_itemgroups_insert_extra_reference
\useitemgroupstyleandcolor\c!symstyle\c!symcolor
\strc_itemgroups_extra_symbol
+ \else
+ \useitemgroupstyleandcolor\c!headstyle\c!headcolor
+ \strc_itemgroups_used_symbol
\fi
\else
- \ifx\strc_itemgroups_extra_symbol\empty
- \useitemgroupstyleandcolor\c!style\c!color
- \strc_itemgroups_used_symbol
- \else
+ \ifconditional\c_strc_itemgroups_symbol
+ \strc_itemgroups_insert_extra_reference
\useitemgroupstyleandcolor\c!symstyle\c!symcolor
\strc_itemgroups_extra_symbol
+ \else
+ \useitemgroupstyleandcolor\c!style\c!color
+ \strc_itemgroups_used_symbol
\fi
\fi}%
- \let\strc_itemgroups_extra_symbol\empty}
+ \let\strc_itemgroups_extra_symbol\empty
+ \setfalse\c_strc_itemgroups_symbol}
\def\strc_itemgroups_make_fitting_box
{\ifdim\wd\b_strc_itemgroups>\itemgroupparameter\c!maxwidth\scaledpoint\relax % brr, sp
@@ -1453,10 +1481,11 @@
\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}%
+ \ifcsname\??itemgroupstack\number\c_strc_itemgroups_collected_current\endcsname
+ \getvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}%
+ \letbeundefined{\??itemgroupstack\number\c_strc_itemgroups_collected_current}%
+ \advance\c_strc_itemgroups_collected_done\plusone
+ \fi
\ifnum\c_strc_itemgroups_collected_done<\c_strc_itemgroups_collected_stored
\expandafter\strc_itemgroups_collected_flush
\fi}
diff --git a/tex/context/base/strc-lab.mkiv b/tex/context/base/strc-lab.mkiv
index 483791462..0039a68fd 100644
--- a/tex/context/base/strc-lab.mkiv
+++ b/tex/context/base/strc-lab.mkiv
@@ -15,82 +15,175 @@
\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}%
+%D Labels are implemented somewhat inefficient but have the advantage that they
+%D can be controlled like other constructions. Who knows when that comes in
+%D handy?
+
+\installcorenamespace{labels}
+
+\installcommandhandler \??labels {label} \??labels % plural hash, else clash with label (or rename that one)
+
+\let\setuplabels\setuplabel
+
+\setuplabel
+ [\c!alternative=\v!intext,
+ \c!headstyle=\v!bold,
+ \c!titlestyle=\v!bold,
+ \c!distance=\zeropoint,
+ \c!width=\v!fit,
+ \c!titledistance=.5\emwidth,
+ \c!margin=\v!no,
+ \c!titleleft=(,
+ \c!titleright=),
+ \c!display=\v!no,
+ \c!titlecommand=,
+ \c!expansion=\v!no,
+ \c!way=\v!by\v!text,
+ \c!prefix=\v!no,
+ \c!prefixconnector=.,
+ \c!text=\currentlabel,
+ \c!number=\v!yes, % else description
+ \c!start=0,
+ \c!state=\v!start,
+ \c!levels=3]
+
+\unexpanded\def\strc_define_commands_label#1#2#3% current level parent
+ {\doifelsenothing{#3}
+ {\normalexpanded{\defineconstruction[#1][\s!handler=\v!label,\c!level=#2]}%
+ \setevalue{\??label#1:\s!parent}{\??label}}%
+ {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!label,\c!level=#2]}%
+ \setevalue{\??label#1:\s!parent}{\??label#3}}%
+ \setuevalue{\e!next #1}{\strc_labels_next }%
+ \setuevalue{\c!reset#1}{\strc_labels_reset }%
+ %setuevalue{\c!set #1}{\strc_labels_set }%
+ \setuevalue {#1}{\strc_labels_command{#1}}}
+
+\appendtoks
+ \ifx\currentlabelparent\empty
+ % clone => parent | subclone => clone | subsubclone => subclone
+ \let\currentlabelsub\empty
+ \strc_define_commands_label
+ {\currentlabelsub\currentlabel}%
+ \plusone
+ \empty
+ \edef\p_levels{\labelparameter\c!levels}%
+ \dostepwiserecurse\plustwo\p_levels\plusone
+ {\strc_define_commands_label
+ {\v!sub\currentlabelsub\currentlabel}%
+ \recurselevel
+ {\currentlabelsub\currentlabel}%
+ \edef\currentlabelsub{\v!sub\currentlabelsub}}%
\else
- \getparameters[\??dd#1][\s!counter=#1,\s!parent=\??dd#2,#3]%
- \dodefinelabelcommands{#1}{\??dd#2}%
+ % clone => parent | subclone => subparent | subsubclone => subsubparent
+ \let\currentlabelsub\empty
+ \edef\p_levels{\labelparameter\c!levels}%
+ \dorecurse\p_levels
+ {\strc_define_commands_label
+ {\currentlabelsub\currentlabel}%
+ \recurselevel
+ {\currentlabelsub\currentlabelparent}%
+ \edef\currentlabelsub{\v!sub\currentlabelsub}}%
+ \fi
+ \edef\p_counter{\labelparameter\s!counter}% can inherit from parent
+ \ifx\p_counter\empty %
+ \let\p_counter\currentlabel
+ \fi
+ \doifcounterelse\p_counter\donothing{\strc_labels_define_counter\p_counter}%
+ \letlabelparameter\s!counter\p_counter
+ \strc_labels_setup_counter\currentlabel
+\to \everydefinelabel
+
+\let\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\setvalue{\??constructioninitializer\v!label}%
+ {\let\currentlabel \currentconstruction
+ \let\constructionparameter \labelparameter
+ \let\detokenizedconstructionparameter\detokenizedlabelparameter
+ \let\letconstructionparameter \letlabelparameter
+ \let\useconstructionstyleandcolor \uselabelstyleandcolor
+ \let\setupcurrentconstruction \setupcurrentlabel
+ % shared with enumerations
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
+ \settrue\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_save\currentconstructionnumber
+ \fi
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \else
+ \setfalse\c_strc_constructions_number_state
+ \fi
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
\fi}
-\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]
+\setvalue{\??constructionfinalizer\v!label}%
+ {\ifconditional\c_strc_constructions_number_state
+ \iftrialtypesetting
+ \strc_counters_restore\currentconstructionnumber
+ \fi
+ \fi}
+
+%D Interfaces:
+
+\let\strc_labels_command\strc_descriptions_command
+\let\strc_labels_next \strc_enumerations_next
+\let\strc_labels_reset \strc_enumerations_reset
+%let\strc_labels_set \strc_enumerations_set
+
+% similar to enumerations
+
+\newtoks\everysetuplabelcounter
+
+\let\v_strc_labels_counter_name\empty
+
+\def\strc_labels_setup_counter#1%
+ {\edef\v_strc_labels_counter_name{#1}%
+ \the\everysetuplabelcounter}
+
+\def\strc_labels_define_counter#1%
+ {\definecounter[#1]%
+ \strc_labels_setup_counter{#1}}
+
+\appendtoks
+ \strc_counter_setup_using_parameter\v_strc_labels_counter_name\labelparameter
+\to \everysetuplabelcounter
+
+\appendtoks
+ \ifx\currentlabel\empty \else
+ \strc_labels_setup_counter\currentlabel
+ \fi
+\to \everysetuplabel
+
+% no start stop here
+
+\expandafter\let\csname\??constructionmainhandler\v!label\expandafter\endcsname\csname\??constructionmainhandler\v!description\endcsname
+
+\unexpanded\setevalue{\??constructioncommandhandler\v!label}%
+ {\csname\??constructionstarthandler\v!construction\endcsname
+ \csname\??constructionstophandler \v!construction\endcsname
+ \endgroup}
+
+\unexpanded\setvalue{\??constructiontexthandler\v!label}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor
+ \strc_labels_text
+ \endgroup}
+
+\let\strc_labels_text\strc_enumerations_text
+
+% inline variant
+
+\defineconstructionalternative
+ [\v!intext]
+ [\c!renderingsetup=\??constructionrenderings:\v!intext]
+
+\startsetups[\??constructionrenderings:\v!intext]
+ \dontleavehmode\box\constructionheadbox
+\stopsetups
\protect \endinput
diff --git a/tex/context/base/strc-lnt.mkvi b/tex/context/base/strc-lnt.mkvi
index f07ce7839..4160360d2 100644
--- a/tex/context/base/strc-lnt.mkvi
+++ b/tex/context/base/strc-lnt.mkvi
@@ -27,11 +27,20 @@
{\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 }}
+ {\ifcsname\??linenote#1\endcsname
+ % there might be files that define the default 'linenote'
+ \ifthirdargument
+ \setupnote[#1][#3]%
+ \else\ifsecondargument
+ \setupnote[#1][#2]%
+ \fi\fi
+ \else
+ \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 }%
+ \fi}
\unexpanded\def\strc_linenotes_direct#1#2%
{\global\advance\c_strc_linenotes\plusone
@@ -41,6 +50,7 @@
\unexpanded\def\strc_linenotes_start#1[#2]#3%
{\global\advance\c_strc_linenotes\plusone
+ \keepunwantedspaces
\strc_linenotes_indeed{#1}{#2}{#3}%
\strc_linenotes_traced{#2}%
\startline[#2]}
@@ -48,19 +58,109 @@
\unexpanded\def\strc_linenotes_stop[#1]%
{\stopline[#1]}
-\unexpanded\def\strc_linenotes_indeed#1#2#3% will be redone
+\let\m_page_lines_previous_to \relax
+\let\m_page_lines_previous_from\relax
+
+\let\m_page_lines_current_to \relax
+\let\m_page_lines_current_from \relax
+
+\newconditional\c_page_lines_current_to
+\newconditional\c_page_lines_current_from
+
+\installcorenamespace{linenotespreviousfrom}
+\installcorenamespace{linenotespreviousto}
+
+\letvalue\??linenotespreviousfrom\empty
+\letvalue\??linenotespreviousto \empty
+
+\def\page_lines_in_from{\in[lr:b:\currentlinenotereference]}
+\def\page_lines_in_to {\in[lr:e:\currentlinenotereference]}
+
+\unexpanded\def\strc_linenotes_range_normal#1% order
+ {\doifreferencefoundelse{lr:b:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_from
+ \ifconditional\c_page_lines_current_from
+ \xdef\m_page_lines_current_from{\currentreferencelinenumber}%
+ \doifreferencefoundelse{lr:e:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_to
+ \ifconditional\c_page_lines_current_to
+ \xdef\m_page_lines_current_to{\currentreferencelinenumber}%
+ \page_lines_in_from
+ \ifx\m_page_lines_current_from\m_page_lines_current_to \else
+ \endash
+ \page_lines_in_to
+ \fi
+ \else
+ \page_lines_in_from
+ \fi
+ \else
+ \page_lines_in_from
+ \fi}
+
+\unexpanded\def\strc_linenotes_range_sparse#1% order
+ {\doifreferencefoundelse{lr:b:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_from
+ \ifconditional\c_page_lines_current_from
+ \xdef\m_page_lines_current_from{\currentreferencelinenumber}%
+ \doifreferencefoundelse{lr:e:\currentlinenotereference}\settrue\setfalse\c_page_lines_current_to
+ \ifconditional\c_page_lines_current_to
+ \xdef\m_page_lines_current_to{\currentreferencelinenumber}%
+ \ifx\m_page_lines_previous_from\m_page_lines_current_from
+ \ifx\m_page_lines_previous_to\m_page_lines_current_to
+ \notationparameter\c!compressseparator
+ \else
+ \page_lines_in_from
+ \fi
+ \else
+ \page_lines_in_from
+ \ifx\m_page_lines_current_from\m_page_lines_current_to
+ \else
+ \endash
+ \page_lines_in_to
+ \fi
+ \fi
+ \else
+ \page_lines_in_from
+ \fi
+ \else
+ \ifx\m_page_lines_previous_from\m_page_lines_current_from
+ \notationparameter\c!compressseparator
+ \else
+ \page_lines_in_from
+ \fi
+ \fi}
+
+\let\currentlinenotereference\empty
+
+\unexpanded\def\strc_linenotes_indeed#1#2#3%
{\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}%
+ \edef\currentlinenotereference{#2}%
+ \xdef\m_page_lines_previous_from{\csname\??linenotespreviousfrom\ifcsname\??linenotespreviousfrom\currentnotation\endcsname\currentnotation\fi\endcsname}%
+ \xdef\m_page_lines_previous_to {\csname\??linenotespreviousto \ifcsname\??linenotespreviousto \currentnotation\endcsname\currentnotation\fi\endcsname}%
+ \doifelse{\notationparameter\c!compress}\v!yes
+ {\let\linenotelinenumber\strc_linenotes_range_sparse}%
+ {\let\linenotelinenumber\strc_linenotes_range_normal}%
\let\currentnote\currentnotation
\letnotationparameter\c!numbercommand\linenotelinenumber% todo: deep hook
\letnoteparameter \c!textcommand \gobbleoneargument % todo: deep hook
- \relax\getvalue{\??linenote#1}{#3}%
+ \getvalue{\??linenote\currentnotation}{#3}%
+ \expandafter\glet\csname\??linenotespreviousfrom\currentnotation\endcsname\m_page_lines_current_from
+ \expandafter\glet\csname\??linenotespreviousto \currentnotation\endcsname\m_page_lines_current_to
\endgroup}
+% where to hook this one in? resetcounter has no hook:
+
+\unexpanded\def\doresetlinenotecompression#1% \strc_linenotes_reset_previous
+ {\expandafter\glet\csname\??linenotespreviousfrom#1\endcsname\empty
+ \expandafter\glet\csname\??linenotespreviousto #1\endcsname\empty}
+
+\definesymbol
+ [\v!compressseparator]
+ [\space\hbox{\vl\thinspace\vl}]
+
+\setupnotations
+ [%c\compress=\v!no,
+ \c!compressseparator=\symbol\v!compressseparator]
+
\let\strc_linenotes_traced\gobbleoneargument
\def\strc_linenotes_traced_indeed#1%
@@ -79,9 +179,14 @@
\unexpanded\def\tracelinenotes
{\let\strc_linenotes_traced\strc_linenotes_traced_indeed}
+%D Use these when not properly nested:
+
+\let\fromlinenote\startlinenote
+\let\tolinenote \stoplinenote
+
% 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/tex/context/base/strc-lst.lua b/tex/context/base/strc-lst.lua
index 48aab78db..424e9e05b 100644
--- a/tex/context/base/strc-lst.lua
+++ b/tex/context/base/strc-lst.lua
@@ -353,7 +353,6 @@ local function filtercollected(names, criterium, number, collected, forced, nest
local cnumbers = sectionnumber.numbers
local metadata = v.metadata
if cnumbers then
---~ print(#cnumbers, depth, concat(cnumbers))
if metadata and not metadata.nolist and (all or names[metadata.name or false]) and #cnumbers >= depth then
local ok = true
for d=1,depth do
@@ -597,7 +596,7 @@ function lists.hasnumberdata(name,n)
local data = lists.result[n]
if data then
local numberdata = data.numberdata
- if numberdata then
+ if numberdata and not numberdata.hidenumber then -- th ehide number is true
return true
end
end
diff --git a/tex/context/base/strc-lst.mkvi b/tex/context/base/strc-lst.mkvi
index 16544f866..965e53700 100644
--- a/tex/context/base/strc-lst.mkvi
+++ b/tex/context/base/strc-lst.mkvi
@@ -28,12 +28,6 @@
\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
@@ -247,7 +241,7 @@
\setupcurrentlist[#settings]%
\the\everystructurelist
% \doif{\listparameter\c!coupling}\v!on{\startlistreferences{#tag}}%
- \doplacestructurelist % maybe inline
+ \strc_lists_place_current % maybe inline
{#list}%
{\listparameter\c!criterium}%
{\listparameter\c!number}%
@@ -364,9 +358,15 @@
\ctxcommand{listuserdata("\currentlist",\currentlistindex,"#name")}%
\dostoptagged}
+\def\rawstructurelistuservariable#name%
+ {\ctxcommand{listuserdata("\currentlist",\currentlistindex,"#name")}}
+
\unexpanded\def\structurelistfirst {\structurelistuservariable\s!first } % s!
\unexpanded\def\structurelistsecond{\structurelistuservariable\s!second} % s!
+\unexpanded\def\rawstructurelistfirst {\rawstructurelistuservariable\s!first } % s!
+\unexpanded\def\rawstructurelistsecond{\rawstructurelistuservariable\s!second} % s!
+
\unexpanded\def\doifstructurelisthaspageelse
{\ctxcommand{doiflisthaspageelse("\currentlist",\currentlistindex)}}
@@ -401,22 +401,22 @@
% TODO: pass extra tag name (contents, figures, bibliography ...)
-\unexpanded\def\doplacestructurelist#list#criterium#number#extras#order% beware, not a user command
+\unexpanded\def\strc_lists_place_current#list#criterium#number#extras#order% beware, not a user command
{\dostarttagged\t!list\empty
\ctxcommand{processlist{
names = "#list",
criterium = "#criterium",
- number = "\number#number",
+ number = "#number",
extras = "#extras",
order = "#order"
}}%
\dostoptagged}
-\unexpanded\def\doanalyzestructurelist#list#criterium#number%
+\unexpanded\def\strc_lists_analyze#list#criterium#number%
{\ctxcommand{analyzelist{
names = "#list",
criterium = "#criterium",
- number = "\number#number"
+ number = "#number"
}}}
\def\firststructureelementinlist#list%
@@ -1020,9 +1020,6 @@
% \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
@@ -1182,6 +1179,10 @@
\letvalue{\??listinteractions\v!all }\v!all
\letvalue{\??listinteractions\v!yes }\v!all
+\def\listboxproperties {\strc_lists_get_reference_attribute}
+\def\listrenderingsetup {\the\t_lists_every_renderingtext}
+\def\listrenderingsynchronize{\the\t_lists_every_renderingsynchronize}
+
\unexpanded\def\strc_lists_interaction_check
{\iflocation
\strc_lists_interaction_check_yes
@@ -1288,7 +1289,7 @@
\let\listlength\!!zerocount
\else
\setupcurrentlist[#settings]%
- \doanalyzestructurelist{#list}{\listparameter\c!criterium}{\listparameter\c!number}%
+ \strc_lists_analyze{#list}{\listparameter\c!criterium}{\listparameter\c!number}%
\normalexpanded{\endgroup\noexpand\edef\noexpand\listlength{\structurelistsize}}%
\fi
\strc_lists_set_mode}
diff --git a/tex/context/base/strc-mar.lua b/tex/context/base/strc-mar.lua
index 66ec04739..c7ef2d4e1 100644
--- a/tex/context/base/strc-mar.lua
+++ b/tex/context/base/strc-mar.lua
@@ -83,7 +83,7 @@ local function resolve(t,k)
if trace_marks_set or trace_marks_get then
report_marks("undefined: name=%s",k)
end
- local crap = { autodefined = true }
+ local crap = { autodefined = true } -- maybe set = 0 and reset = 0
t[k] = crap
return crap
else
@@ -264,13 +264,16 @@ function marks.set(name,value)
dn = data[name]
end
dn.set = topofstack
+ if not dn.reset then
+ dn.reset = 0 -- in case of selfdefined
+ end
local top = stack[topofstack]
local new = { }
if top then
for k, v in next, top do
local d = data[k]
- local r = d.reset
- local s = d.set
+ local r = d.reset or 0
+ local s = d.set or 0
if r <= topofstack and s < r then
new[k] = false
else
@@ -689,6 +692,6 @@ commands.fetchtwomarks = marks.fetchtwomarks
commands.fetchallmarks = marks.fetchallmarks
function commands.doifelsemarking(str) -- can be shortcut
- commands.testcase(marks.exists(str))
+ commands.doifelse(marks.exists(str))
end
diff --git a/tex/context/base/strc-mat.mkiv b/tex/context/base/strc-mat.mkiv
index 121808cd1..ec4d7f643 100644
--- a/tex/context/base/strc-mat.mkiv
+++ b/tex/context/base/strc-mat.mkiv
@@ -1,4 +1,5 @@
%D \module
+%D \module
%D [ file=strc-mat,
%D version=2008.10.20,
%D title=\CONTEXT\ Structure Macros,
@@ -39,12 +40,12 @@
\c!expansion=\v!yes, % maybe automatically
\c!spacebefore=\v!big,
\c!spaceafter=\formulaparameter\c!spacebefore,
- \c!leftmargin=\!!zeropoint,
- \c!rightmargin=\!!zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
\c!indentnext=\v!no,
\c!alternative=\s!default,
\c!strut=\v!no,
- \c!distance=1em]
+ \c!distance=\emwidth]
\setupsubformulas % subformulas could be last in chain
[\c!indentnext=\formulaparameter\c!indentnext]
@@ -54,13 +55,12 @@
\defineconversionset
[\v!formula]
- [numbers,characters]
+ [numbers,characters] % no \v! ?
\strc_counter_preset_using_parameter\setupformulas\sharedcounterparameter
\appendtoks
\strc_counter_setup_using_parameter\v!formula\formulaparameter
- \strc_counters_check_setup\v!formula % yes or no
\to \everysetupformula
\setupformulas
@@ -68,22 +68,22 @@
\appendtoks
\normalexpanded{\definelist[\currentformula]}% is expansion needed?
- \setuevalue{\e!start\currentformula\v!formula}{\dostartformula{\currentformula}}%
- \setuevalue{\e!stop \currentformula\v!formula}{\dostopformula}%
+ \setuevalue{\e!start\currentformula\v!formula}{\strc_formulas_start_formula{\currentformula}}%
+ \setuevalue{\e!stop \currentformula\v!formula}{\strc_formulas_stop_formula}%
\to \everydefineformula
\definelist[\v!formula]
-\setuvalue{\e!start\v!formula}{\dostartformula{}}
-\setuvalue{\e!stop \v!formula}{\dostopformula}
+\setuvalue{\e!start\v!formula}{\strc_formulas_start_formula{}}
+\setuvalue{\e!stop \v!formula}{\strc_formulas_stop_formula}
-\let\dostartformula\relax % defined later
-\let\dostopformula \relax % defined later
+\let\strc_formulas_start_formula\relax % defined later
+\let\strc_formulas_stop_formula \relax % defined later
-\unexpanded\def\defineformulaalternative % this might change ... start and stop can become keys
- {\dotripleargument\dodefineformulaalternative} % to the general define .. s!startcommand
+\unexpanded\def\defineformulaalternative % this might change ... start and stop can become keys
+ {\dotripleargument\strc_formulas_define_alternative} % to the general define .. s!startcommand
-\def\dodefineformulaalternative[#1][#2][#3]%
+\def\strc_formulas_define_alternative[#1][#2][#3]%
{\setvalue{\e!start#1\v!formula}{#2}%
\setvalue{\e!stop #1\v!formula}{#3}}
@@ -126,8 +126,8 @@
% implementation
-\def\storecurrentformulanumber#1#2#3#4#5% ref, todo:str, \sync % todo: title etc (like float)
- {\settrue\handleformulanumber
+\unexpanded\def\strc_formulas_store_number#1#2#3#4#5% ref, todo:str, \sync % todo: title etc (like float)
+ {\settrue\c_strc_formulas_handle_number
\strc_counters_register_component
{formula}%
\setupcurrentformula \formulaparameter \detokenizedformulaparameter
@@ -143,68 +143,75 @@
% modes: 0=unset, 1=forced, 2=none, 3=reference
-\newconstant\placeformulanumbermode
-\newconstant\formulasnumbermode
-\newconstant\subformulasnumbermode
-\newconstant\nestedformulanumbermode
+\newconstant\c_strc_formulas_place_number_mode
+\newconstant\c_strc_formulas_number_mode
+\newconstant\c_strc_formulas_sub_number_mode
+\newconstant\c_strc_formulas_nested_number_mode
\appendtoks
- \placeformulanumbermode \zerocount
- \formulasnumbermode \zerocount
- \subformulasnumbermode \zerocount
- \nestedformulanumbermode\zerocount
+ \c_strc_formulas_place_number_mode \zerocount
+ \c_strc_formulas_number_mode \zerocount
+ \c_strc_formulas_sub_number_mode \zerocount
+ \c_strc_formulas_nested_number_mode\zerocount
\to \everyresetformulas
-\newconditional\handleformulanumber
-\newconditional\incrementformulanumber
-
-\newconditional\insideplaceformula
-\newconditional\insideplacesubformula
-\newconditional\insideformulas
-\newconditional\insidesubformulas
+\newconditional\c_strc_formulas_handle_number
+\newconditional\c_strc_formulas_increment
+\newconditional\c_strc_formulas_inside_place
+\newconditional\c_strc_formulas_inside_place_sub
+\newconditional\c_strc_formulas_inside_formulas
+\newconditional\c_strc_formulas_inside_formulas_sub
\appendtoks
- \global\setfalse\insideplaceformula
- \global\setfalse\insideplacesubformula
+ \global\setfalse\c_strc_formulas_inside_place
+ \global\setfalse\c_strc_formulas_inside_place_sub
\to \everyresetformulas
-\def\handleplaceformulanumbering % place formula
- {\settrue\handleformulanumber
- \docheckformulareference\placeformulanumbermode\currentplaceformulareference
- \glet\doplaceformulanumber \doplaceformulanumberindeed
- \glet\donestedformulanumber\donestedformulanumberindeed}
+\def\strc_formulas_place_numbering % place formula
+ {\settrue\c_strc_formulas_handle_number
+ \strc_formulas_check_reference\c_strc_formulas_place_number_mode\currentplaceformulareference
+ \glet\strc_formulas_place_number\strc_formulas_place_number_indeed
+ \glet\strc_formulas_place_number_nested\strc_formulas_place_number_nested_indeed}
-\def\handleformulasnumbering % formulas
- {\docheckformulareference\formulasnumbermode\currentformulareference}
+\def\strc_formulas_handle_number % formulas
+ {\strc_formulas_check_reference\c_strc_formulas_number_mode\currentformulareference}
-\def\handlesubformulasnumbering % sub formulas
- {\docheckformulareference\subformulasnumbermode\currentsubformulasreference
+\def\strc_formulas_handle_sub_number_indeed % sub formulas
+ {\strc_formulas_check_reference\c_strc_formulas_sub_number_mode\currentsubformulasreference
\strc_counters_increment\v!formula
- \storecurrentformulanumber
+ \strc_formulas_store_number
\currentsubformulasreference
\empty
\currentsubformulasnumber
\currentsubformulassynchronize
- \currentsubformulasattribute
- }
+ \currentsubformulasattribute}
+
+\def\strc_formulas_handle_sub_number % sub formulas
+ {\iftrialtypesetting
+ \strc_counters_save\v!formula
+ \strc_formulas_handle_sub_number_indeed
+ \strc_counters_restore\v!formula
+ \else
+ \strc_formulas_handle_sub_number_indeed
+ \fi}
-\let\dotraceformulareferencestate\relax
-\let\doshowformulareferencestate \relax
+\let\strc_formulas_reference_trace\relax
+\let\strc_formulas_reference_show \relax
-% \def\dotraceformulareferencestate
+% \def\strc_formulas_reference_trace
% {\rlap{\hbox{\quad\tt\txx[%
-% \number\placeformulanumbermode,%
-% \number\formulasnumbermode,%
-% \number\subformulasnumbermode,%
-% \number\nestedformulanumbermode
+% \number\c_strc_formulas_place_number_mode,%
+% \number\c_strc_formulas_number_mode,%
+% \number\c_strc_formulas_sub_number_mode,%
+% \number\c_strc_formulas_nested_number_mode
% ]}}}
-% \def\doshowformulareferencestate
+% \def\strc_formulas_reference_show
% {\writestatus{\v!formula}%
-% {place: \number\placeformulanumbermode,\space
-% formula: \number\formulasnumbermode,\space
-% subformula: \number\subformulasnumbermode,\space
-% nested: \number\nestedformulanumbermode]}}
+% {place: \number\c_strc_formulas_place_number_mode,\space
+% formula: \number\c_strc_formulas_number_mode,\space
+% subformula: \number\c_strc_formulas_sub_number_mode,\space
+% nested: \number\c_strc_formulas_nested_number_mode]}}
\unexpanded\def\placecurrentformulanumber
{\rm % nodig ?
@@ -216,12 +223,12 @@
\namedtaggedlabeltexts
\t!formulalabel \v!formula
\t!formulanumber\v!formula
- {\ignorespaces\doplacecurrentformulanumber\removeunwantedspaces}%
+ {\ignorespaces\strc_formulas_place_current_number\removeunwantedspaces}%
\formulaparameter\c!right}%
\doif{\formulaparameter\c!location}\v!left{\hskip\formulaparameter\c!distance}}
-\def\doplacecurrentformulanumber
- {\dohandlecurrentformulareferences
+\unexpanded\def\strc_formulas_place_current_number
+ {\strc_formulas_handle_current_references
\labeltexts\currentformula{\convertedcounter[\v!formula][]}}
% \def\theboxdestinationattribute#1{\iflocation\ifx#1\relax\else\ifx#1\empty\else attr \destinationattribute#1\fi\fi\fi}
@@ -281,10 +288,10 @@
% currently we do the number, some day we will do the (sub) formula
-\def\dohandlecurrentformulareferences
- {\doshowformulareferencestate
- \ifnum\placeformulanumbermode=\plusthree
- \storecurrentformulanumber
+\def\strc_formulas_handle_current_references
+ {\strc_formulas_reference_show
+ \ifnum\c_strc_formulas_place_number_mode=\plusthree
+ \strc_formulas_store_number
\currentplaceformulareference
\empty
\currentplaceformulanumber
@@ -294,8 +301,8 @@
\glet\currentplaceformulasynchronize\relax
\theformuladestinationattribute\currentplaceformulaattribute
\fi
- \ifnum\formulasnumbermode=\plusthree
- \storecurrentformulanumber
+ \ifnum\c_strc_formulas_number_mode=\plusthree
+ \strc_formulas_store_number
\currentformulasreference
\empty
\currentformulasnumber
@@ -305,12 +312,12 @@
\glet\currentformulassynchronize\relax
\theformuladestinationattribute\currentformulasattribute
\fi
- \ifnum\subformulasnumbermode=\plusthree
+ \ifnum\c_strc_formulas_sub_number_mode=\plusthree
\currentsubformulassynchronize
\glet\currentsubformulassynchronize\relax
\fi
- \ifnum\nestedformulanumbermode=\plusthree
- \storecurrentformulanumber
+ \ifnum\c_strc_formulas_nested_number_mode=\plusthree
+ \strc_formulas_store_number
\currentnestedformulareference
\empty
\currentnestedformulanumber
@@ -323,55 +330,74 @@
% needs checking ... too many:
-\def\dohandleformulanumbering
+\def\strc_formulas_handle_numbering_indeed
{\strc_counters_increment\v!formula
\doiftext\currentplaceformulasuffix{\strc_counters_setown_sub\v!formula\plustwo\currentplaceformulasuffix}%
\placecurrentformulanumber}
-\def\dohandlesubformulanumbering
- {\doiftextelse\currentsubformulasuffix
+\def\strc_formulas_handle_numbering
+ {\iftrialtypesetting
+ \strc_counters_save\v!formula
+ \strc_formulas_handle_numbering_indeed
+ \strc_counters_restore\v!formula
+ \else
+ \strc_formulas_handle_numbering_indeed
+ \fi}
+
+\def\strc_formulas_handle_sub_numbering_indeed
+ {\let\strc_formulas_handle_sub_numbering\relax % else error: see math/numbering-001.tex
+ \doiftextelse\currentsubformulasuffix
{\strc_counters_setown_sub\v!formula\plustwo\currentsubformulasuffix}
{\strc_counters_increment_sub\v!formula\plustwo}%
- \placecurrentformulanumber}
+ \placecurrentformulanumber}
-\def\dododoformulanumber
- {\ifconditional\handleformulanumber
+\def\strc_formulas_handle_sub_numbering
+ {\iftrialtypesetting
+ \strc_counters_save\v!formula
+ \strc_formulas_handle_sub_numbering_indeed
+ \strc_counters_restore\v!formula
+ \else
+ \strc_formulas_handle_sub_numbering_indeed
+ \fi}
+
+\def\strc_formulas_number_indeed
+ {\ifconditional\c_strc_formulas_handle_number
\hbox\bgroup
% main counter
- \ifconditional\insidesubformulas
+ \ifconditional\c_strc_formulas_inside_formulas_sub
% nothing
\else
- \ifcase\formulasnumbermode
- \ifcase\placeformulanumbermode
- \dohandleformulanumbering
+ \ifcase\c_strc_formulas_number_mode
+ \ifcase\c_strc_formulas_place_number_mode
+ \strc_formulas_handle_numbering
\or
- \dohandleformulanumbering
+ \strc_formulas_handle_numbering
\or
% nothing
\or
- \dohandleformulanumbering
+ \strc_formulas_handle_numbering
\fi
\or
- \dohandleformulanumbering
+ \strc_formulas_handle_numbering
\or
% nothing
\or
- \dohandleformulanumbering
+ \strc_formulas_handle_numbering
\fi
\fi
% subcounter
- \ifconditional\insidesubformulas
- \ifcase\subformulasnumbermode
+ \ifconditional\c_strc_formulas_inside_formulas_sub
+ \ifcase\c_strc_formulas_sub_number_mode
% nothing
\or
- \dohandlesubformulanumbering
+ \strc_formulas_handle_sub_numbering
\or
% nothing
\or
- \dohandlesubformulanumbering
+ \strc_formulas_handle_sub_numbering
\fi
\fi
- \dotraceformulareferencestate
+ \strc_formulas_reference_trace
\egroup
\fi}
@@ -393,10 +419,10 @@
%D
%D Otherwise we get a missing \type {$$} error reported.
-\def\resetdisplaymatheq
+\unexpanded\def\resetdisplaymatheq % when used?
{\let\normalleqno\gobbleoneargument \let\leqno\gobbleoneargument
\let\normalreqno\gobbleoneargument \let\eqno \gobbleoneargument
- \let\doplaceformulanumber\empty}
+ \let\strc_formulas_place_number\relax}
%D \macros
%D {startsubformulas}
@@ -431,28 +457,36 @@
% we don't use the skip's
-\def\forgetdisplayskips % to do
+\unexpanded\def\strc_formulas_forget_display_skips
{\abovedisplayskip \zeropoint
\belowdisplayskip \zeropoint
\abovedisplayshortskip\zeropoint
\belowdisplayshortskip\zeropoint}
-\def\predisplaysizethreshhold{2em} % was 3em
+% \def\predisplaysizethreshhold{2\emwidth} % was 3\emwidth
-\def\leftdisplayskip {\leftskip}
-\def\rightdisplayskip {\rightskip}
-\def\leftdisplaymargin {\formulaparameter\c!leftmargin}
-\def\rightdisplaymargin {\formulaparameter\c!rightmargin}
+\newdimen\d_strc_formulas_display_skip_left
+\newdimen\d_strc_formulas_display_skip_right
+\newdimen\d_strc_formulas_display_margin_left
+\newdimen\d_strc_formulas_display_margin_right
+\newdimen\d_strc_formulas_display_pre_threshold
+\newskip \d_strc_formulas_display_skip_par
-\def\beforedisplayspace
- {\doifnot{\formulaparameter\c!spacebefore}\v!none{\blank[\formulaparameter\c!spacebefore]}}
+\unexpanded\def\beforedisplayspace
+ {\edef\p_spacebefore{\formulaparameter\c!spacebefore}%
+ \ifx\p_spacebefore\v!none \else
+ \blank[\p_spacebefore]%
+ \fi}
-\def\afterdisplayspace
- {\doifnot{\formulaparameter\c!spaceafter }\v!none{\blank[\formulaparameter\c!spaceafter ]}}
+\unexpanded\def\afterdisplayspace
+ {\edef\p_spaceafter{\formulaparameter\c!spaceafter}%
+ \ifx\p_spaceafter\v!none \else
+ \blank[\p_spaceafter]%
+ \fi}
-\def\setdisplaydimensions
- {\displayindent\leftdisplayskip
- \advance\displayindent\leftdisplaymargin
+\unexpanded\def\setdisplaydimensions
+ {\displayindent\d_strc_formulas_display_skip_left
+ \advance\displayindent\d_strc_formulas_display_margin_left
\displaywidth\hsize
%\setlocalhsize
%\displaywidth\localhsize
@@ -461,15 +495,14 @@
\else
\advance\displaywidth\hangindent
\fi
- \advance\displaywidth\dimexpr-\displayindent-\rightdisplayskip-\rightdisplaymargin\relax
+ \advance\displaywidth\dimexpr-\displayindent-\d_strc_formulas_display_skip_right-\d_strc_formulas_display_margin_right\relax
\hsize\displaywidth} % new, else overfull in itemize
-\unexpanded\def\dostartformula#1%
- {\dodoubleempty\dodostartformula[#1]}
+\unexpanded\def\strc_formulas_start_formula#1%
+ {\dodoubleempty\strc_formulas_start_formula_indeed[#1]}
-\newskip\formulaparskip
-\newskip\formulastrutht
-\newskip\formulastrutdp
+% \newskip\formulastrutht
+% \newskip\formulastrutdp
%D \startbuffer
%D \startformula[9pt] x = 1 \stopformula
@@ -478,38 +511,56 @@
%D
%D \typebuffer \getbuffer
-\def\dodostartformula[#1][#2]% setting leftskip adaption is slow !
+\unexpanded\def\strc_formulas_start_formula_indeed[#1][#2]% setting leftskip adaption is slow !
{\bgroup % HERE
\def\currentformula{#1}%
\dostarttagged\t!formula\currentformula
\the\everybeforedisplayformula
- \formulaparskip\parskip
- \formulastrutdp\strutdepth
- \formulastrutht\strutheight
- \doifsomething{#2}{\switchtoformulabodyfont[#2]}%
- \parskip\formulaparskip
- % may look better in itemizations
- \doif{\formulaparameter\c!option}\v!middle
- {\def\leftdisplayskip{\zeropoint}%
- \def\rightdisplayskip{\zeropoint}}%
- % this was an experiment
- \doifsomething{\formulaparameter\c!margin}% so we test first
- {\dosetleftskipadaption{\formulaparameter\c!margin}%
- \edef\leftdisplaymargin{\the\leftskipadaption}}% overloaded
- \long\def\dostartformula##1{\bgroup\dostarttagged\t!subformula\def\dostopformula{\dostoptagged\egroup}}%
- \freezedimenmacro\leftdisplayskip
- \freezedimenmacro\rightdisplayskip
- \freezedimenmacro\leftdisplaymargin
- \freezedimenmacro\rightdisplaymargin
- \freezedimenmacro\predisplaysizethreshhold
- \forgetdisplayskips
+ \d_strc_formulas_display_skip_par\parskip\relax
+ %\formulastrutdp\strutdepth
+ %\formulastrutht\strutheight
+ \edef\p_option {\formulaparameter\c!option}%
+ \edef\p_margin {\formulaparameter\c!margin}%
+ \edef\p_bodyfont{#2}%
+ %\ifx\p_bodyfont\empty
+ % \edef\p_bodyfont{\formulaparameter\c!bodyfont}%
+ %\fi
+ \ifx\p_bodyfont\empty \else
+ \switchtoformulabodyfont[#2]%
+ \fi
+ \parskip\d_strc_formulas_display_skip_par\relax
+ \ifx\p_option\v!middle
+ \d_strc_formulas_display_skip_left \zeropoint
+ \d_strc_formulas_display_skip_right\zeropoint
+ \else
+ \d_strc_formulas_display_skip_left \leftskip
+ \d_strc_formulas_display_skip_right\rightskip
+ \fi
+ \d_strc_formulas_display_margin_left \formulaparameter\c!leftmargin \relax
+ \d_strc_formulas_display_margin_right\formulaparameter\c!rightmargin\relax
+ \ifx\p_margin\empty \else
+ \dosetleftskipadaption\p_margin
+ \d_strc_formulas_display_margin_left\leftskipadaption
+ \fi
+ \let\strc_formulas_start_formula\strc_formulas_start_formula_nested
+ %\freezedimenmacro\predisplaysizethreshhold
+ \strc_formulas_forget_display_skips
\getvalue{\e!start\formulaparameter\c!alternative\v!formula}}
+\unexpanded\def\strc_formulas_start_formula_nested#1%
+ {\bgroup
+ \let\strc_formulas_stop_formula\strc_formulas_stop_formula_nested
+ \dostarttagged\t!subformula}
+
+\unexpanded\def\strc_formulas_stop_formula_nested
+ {\dostoptagged
+ \egroup}
+
% tagging of formulanumbers is not ok (we get two display maths blobs)
-\unexpanded\def\dostopformula
+\unexpanded\def\strc_formulas_stop_formula
{\dostarttagged\t!formulacaption\empty
- \doplaceformulanumber
+ \strc_formulas_place_number
\dostoptagged
\dostarttagged\t!formulacontent\empty
\getvalue{\e!stop\formulaparameter\c!alternative\v!formula}%
@@ -520,27 +571,31 @@
\egroup
\hangafter\minusone % added for side floats
\hangindent\zeropoint % added for side floats
- \setfalse\handleformulanumber
+ \setfalse\c_strc_formulas_handle_number
\the\everyresetformulas
\dorechecknextindentation} % here ?
% experiment:
\appendtoks
- \edef\currentformulagrid{\formulaparameter\c!grid}%
- \ifx\currentformulagrid\empty \else
- \spac_grids_snap_value_auto\currentformulagrid
+ \edef\p_grid{\formulaparameter\c!grid}%
+ \ifx\p_grid\empty \else
+ \spac_grids_snap_value_auto\p_grid
\fi
\to \everybeforedisplayformula
-\def\switchtoformulabodyfont{\switchtobodyfont}
+\unexpanded\def\switchtoformulabodyfont
+ {\switchtobodyfont}
-\setuvalue{\v!formula}{\dosingleempty\doformula}
+\setuvalue{\v!formula}{\dosingleempty\strc_formulas_formula}
-\def\doformula[#1]#2% todo: tagged
+\def\strc_formulas_formula[#1]#2% todo: tagged
{\begingroup
- \doifsomething{#1}{\switchtoformulabodyfont[#1]}%
- % not : \def\doformula[##1]##2{\mathematics{##2}}%
+ \edef\p_bodyfont{#1}%
+ \ifx\p_bodyfont\empty \else
+ \switchtoformulabodyfont[\p_bodyfont]%
+ \fi
+ % not : \def\strc_formulas_formula[##1]##2{\mathematics{##2}}%
\mathematics{#2}%
\endgroup}
@@ -558,7 +613,7 @@
\beforedisplayspace
\par
\ifvmode
- \prevdepth-\maxdimen % texbook pagina 79-80
+ \prevdepth-\maxdimen % texbook pagina 79-80
\fi
\noindent % else funny hlist with funny baselineskip
$$% \Ustartdisplaymath
@@ -601,26 +656,26 @@
% \fakewords{20}{40}
\unexpanded\def\startsubformulas
- {\dosingleempty\dostartsubformulas}
+ {\dosingleempty\strc_formulas_start_sub_formulas}
-\def\dostartsubformulas[#1]%
+\def\strc_formulas_start_sub_formulas[#1]%
{\edef\currentsubformulasreference{#1}%
- \global\settrue\insidesubformulas
- \handlesubformulasnumbering}
+ \global\settrue\c_strc_formulas_inside_formulas_sub
+ \strc_formulas_handle_sub_number}
\unexpanded\def\stopsubformulas
{\nonoindentation
\useindentnextparameter\subformulaparameter
\the\everyresetformulas % to be checked
- \global\setfalse\insidesubformulas
+ \global\setfalse\c_strc_formulas_inside_formulas_sub
\dorechecknextindentation} % here ?
%D Named subformulas (to be redone)
\unexpanded\def\startnamedsubformulas
- {\dosingleempty\dostartnamedsubformulas}
+ {\dosingleempty\strc_formulas_start_named_sub_formulas}
-\def\dostartnamedsubformulas[#1]#2%
+\def\strc_formulas_start_named_sub_formulas[#1]#2%
{\setformulalistentry{#2}%
\startsubformulas[#1]}
@@ -639,19 +694,19 @@
%D \typebuffer \getbuffer
\unexpanded\def\startformulas
- {\dosingleempty\dostartformulas}
+ {\dosingleempty\strc_formulas_start_formulas}
-\def\dostartformulas[#1]#2\stopformulas % new / to be internationalized
+\def\strc_formulas_start_formulas[#1]#2\stopformulas % new / to be internationalized
{\bgroup
\dostarttagged\t!formulaset\empty
- \global\settrue\insideformulas
+ \global\settrue\c_strc_formulas_inside_formulas
\edef\currentformulasreference{#1}%
- \handleformulasnumbering
+ \strc_formulas_handle_number
\let\currentformula\empty
- \forgetdisplayskips
+ \strc_formulas_forget_display_skips
\startdisplaymath
\setlocalhsize
- \long\unexpanded\def\startformula##1\stopformula
+ \unexpanded\def\startformula##1\stopformula
{\advance\scratchcounter\plusone}%
\scratchcounter\zerocount
#2% preroll
@@ -660,122 +715,135 @@
\fi
\hbox to \localhsize \bgroup
\hss
- \def\normalstartformula{\vskip-\strutdepth\Ustartdisplaymath}% i hate this
- \def\normalstopformula {\Ustopdisplaymath}%
- \unexpanded\def\startformula {\Ustartmath\vcenter\bgroup\normalstartformula}%
- \unexpanded\def\stopformula {\normalstopformula\egroup\Ustopmath\hss}%
+ \let\startformula\strc_formulas_nested_formula_start
+ \let\stopformula \strc_formulas_nested_formula_stop
#2%
\egroup
\stopdisplaymath
- \global\setfalse\insideformulas
+ \global\setfalse\c_strc_formulas_inside_formulas
\dostoptagged
\egroup
\the\everyresetformulas
\hangafter\minusone % added for side floats
\hangindent\zeropoint} % added for side floats
+\unexpanded\def\strc_formulas_nested_formula_start
+ {\Ustartmath
+ \vcenter\bgroup
+ \vskip-\strutdepth
+ \Ustartdisplaymath}
+
+\unexpanded\def\strc_formulas_nested_formula_stop
+ {\Ustopdisplaymath
+ \egroup
+ \Ustopmath
+ \hss}
+
% place
-\def\inhibitformulanumberflag{-}
-\def\forceformulanumberflag {+}
+\def\m_strc_formulas_flag_inhibit{-}
+\def\m_strc_formulas_flag_force {+}
-\def\docheckformulareference#1#2%
+\def\strc_formulas_check_reference#1#2%
{#1\unless\ifx\namedformulaentry\empty % \relax % new 29/8/2010
\plusthree
\else\ifx#2\empty
\zerocount
- \else\ifx#2\forceformulanumberflag
+ \else\ifx#2\m_strc_formulas_flag_force
\plusone
- \else\ifx#2\inhibitformulanumberflag
+ \else\ifx#2\m_strc_formulas_flag_inhibit
\plustwo
\else
\plusthree
\fi\fi\fi\fi}
-\unexpanded\def\formulanumber{\doformulanumber} % for the moment
+\unexpanded\def\formulanumber
+ {\strc_formulas_number} % for the moment
-\def\doformulanumber
- {\dosingleempty\dodoformulanumber}
+\def\strc_formulas_number
+ {\dosingleempty\strc_formulas_number_again}
-\def\dodoformulanumber[#1]%
+\def\strc_formulas_number_again[#1]%
{\def\currentformulareference{#1}%
- \dosinglegroupempty\dododoformulanumber}
-
-\def\redoformulanumber#1%
- {\def\currentformulasuffix{#1}%
- \dododoformulanumber}
+ \dosinglegroupempty\strc_formulas_number_indeed}
\unexpanded\def\placeformula
- {\global\settrue\insideplaceformula
- \settrue\incrementformulanumber
- \dosingleempty\doplaceformula}
+ {\global\settrue\c_strc_formulas_inside_place
+ \settrue\c_strc_formulas_increment
+ \dosingleempty\strc_formulas_place}
\unexpanded\def\placesubformula
- {\global\settrue\insideplacesubformula
- \setfalse\incrementformulanumber
- \dosingleempty\doplaceformula}
+ {\global\settrue\c_strc_formulas_inside_place_sub
+ \setfalse\c_strc_formulas_increment
+ \dosingleempty\strc_formulas_place}
-\def\doplaceformula[#1]%
+\def\strc_formulas_place[#1]%
{\def\currentplaceformulareference{#1}%
\let\currentplaceformulasuffix\empty
- \doifnextbgroupelse\moreplaceformula\redoplaceformula} % [ref]{}
+ \doifnextbgroupelse\strc_formulas_place_yes\strc_formulas_place_nop\strc_formulas_place_nop} % [ref]{}
-\def\moreplaceformula#1%
+\def\strc_formulas_place_yes#1%
{\def\currentplaceformulasuffix{#1}%
- \redoplaceformula}
+ \strc_formulas_place_nop}
-\def\redoplaceformula
- {\doifnextcharelse$\dispplaceformula\dodoplaceformula} % [ref]$$ [ref]\start
+\def\strc_formulas_place_nop
+ {\doifnextcharelse$\strc_formulas_place_pickup\strc_formulas_place_indeed} % [ref]$$ [ref]\start
-\def\dodoplaceformula
- {\handleplaceformulanumbering}
+\def\strc_formulas_place_indeed
+ {\strc_formulas_place_numbering}
-\def\dispplaceformula$$#1$$%
- {\handleplaceformulanumbering
- \dostartformula{}#1\dostopformula}
+\def\strc_formulas_place_pickup$$#1$$%
+ {\strc_formulas_place_numbering
+ \strc_formulas_start_formula{}#1\strc_formulas_stop_formula}
\let\startplaceformula\placeformula
\let\stopplaceformula \relax
% to be checked
-\let\doplaceformulanumber \relax
-\let\donestedformulanumber\gobbletwoarguments
+\let\strc_formulas_place_number \relax
+\let\strc_formulas_place_number_nested\gobbletwoarguments
-\def\donestedformulanumberindeed#1#2%
+\def\strc_formulas_place_number_nested_indeed#1#2%
{\def\currentnestedformulareference{#1}%
\def\currentnestedformulasuffix{#2}%
- \glet\doplaceformulanumber\relax
- \docheckformulareference\nestedformulanumbermode\currentnestedformulareference
- \ifcase\nestedformulanumbermode
+ \glet\strc_formulas_place_number\relax
+ \strc_formulas_check_reference\c_strc_formulas_nested_number_mode\currentnestedformulareference
+ \ifcase\c_strc_formulas_nested_number_mode
% nothing
\or
- \doformulanumber
+ \strc_formulas_number % hm, looks ahead for []
\or
% nothing
\or
- \doformulanumber
+ \strc_formulas_number % hm, looks ahead for []
\fi}
-\def\doplaceformulanumberindeed
- {\glet\doplaceformulanumber\relax
+\def\strc_formulas_place_number_indeed
+ {\glet\strc_formulas_place_number\relax
\doifelse{\formulaparameter\c!location}\v!left
- {\normalleqno{\dododoformulanumber}}
- {\normalreqno{\dododoformulanumber}}}
+ {\normalleqno{\strc_formulas_number_indeed}}
+ {\normalreqno{\strc_formulas_number_indeed}}}
% todo
\unexpanded\def\placenamedformula
- {\dosingleempty\doplacenamedformula}
+ {\dosingleempty\strc_formulase_place_named}
-\def\doplacenamedformula[#1]#2%
+\def\strc_formulase_place_named
{\iffirstargument
- \def\next{\placeformula[#1]}%
+ \expandafter\strc_formulase_place_named_yes
\else
- \let\next\placeformula
- \fi
- \setformulalistentry{#2}%
- \next}
+ \expandafter\strc_formulase_place_named_nop
+ \fi}
+
+\def\strc_formulase_place_named_yes[#1]#2%
+ {\setformulalistentry{#2}%
+ \placeformula[#1]}
+
+\def\strc_formulase_place_named_nop[#1]#2%
+ {\setformulalistentry{#2}%
+ \placeformula}
\let\namedformulaentry\empty % \relax % this will become a key/value so that we can do bookmarks
diff --git a/tex/context/base/strc-not.lua b/tex/context/base/strc-not.lua
index 6a3f3bfad..d71b371ab 100644
--- a/tex/context/base/strc-not.lua
+++ b/tex/context/base/strc-not.lua
@@ -13,18 +13,19 @@ local texcount = tex.count
local trace_notes = false trackers.register("structures.notes", function(v) trace_notes = v end)
local trace_references = false trackers.register("structures.notes.references", function(v) trace_references = v end)
-local report_notes = logs.reporter("structure","notes")
+local report_notes = logs.reporter("structure","notes")
-local structures = structures
-local helpers = structures.helpers
-local lists = structures.lists
-local sections = structures.sections
-local counters = structures.counters
-local notes = structures.notes
-local references = structures.references
+local structures = structures
+local helpers = structures.helpers
+local lists = structures.lists
+local sections = structures.sections
+local counters = structures.counters
+local notes = structures.notes
+local references = structures.references
+local counterspecials = counters.specials
-notes.states = notes.states or { }
-lists.enhancers = lists.enhancers or { }
+notes.states = notes.states or { }
+lists.enhancers = lists.enhancers or { }
storage.register("structures/notes/states", notes.states, "structures.notes.states")
@@ -33,10 +34,18 @@ local notedata = { }
local variables = interfaces.variables
local context = context
+local commands = commands
-- state: store, insert, postpone
-function notes.store(tag,n)
+local function store(tag,n)
+ -- somewhat weird but this is a cheap hook spot
+ if not counterspecials[tag] then
+ counterspecials[tag] = function(tag)
+ context.doresetlinenotecompression(tag) -- maybe flag that controls it
+ end
+ end
+ --
local nd = notedata[tag]
if not nd then
nd = { }
@@ -53,7 +62,13 @@ function notes.store(tag,n)
end
state.start = state.start or nnd
end
- context(#nd)
+ return #nd
+end
+
+notes.store = store
+
+function commands.storenote(tag,n)
+ context(store(tag,n))
end
local function get(tag,n) -- tricky ... only works when defined
@@ -84,16 +99,59 @@ notes.getn = getn
-- we could make a special enhancer
-function notes.listindex(tag,n)
+local function listindex(tag,n)
local ndt = notedata[tag]
return ndt and ndt[n]
end
+notes.listindex = listindex
+
+function commands.notelistindex(tag,n)
+ context(listindex(tag,n))
+end
+
+local function setstate(tag,newkind)
+ local state = notestates[tag]
+ if trace_notes then
+ report_notes("setting state of '%s' from %s to %s",tag,(state and state.kind) or "unset",newkind)
+ end
+ if not state then
+ state = {
+ kind = newkind
+ }
+ notestates[tag] = state
+ elseif newkind == "insert" then
+ if not state.start then
+ state.kind = newkind
+ end
+ else
+ state.kind = newkind
+ end
+ -- state.start can already be set and will be set when an entry is added or flushed
+ return state
+end
+
+local function getstate(tag)
+ local state = notestates[tag]
+ return state and state.kind or "unknown"
+end
+
+notes.setstate = setstate
+notes.getstate = getstate
+
+commands.setnotestate = setstate
+
+function commands.getnotestate(tag)
+ context(getstate(tag))
+end
+
function notes.define(tag,kind,number)
- local state = notes.setstate(tag,kind)
+ local state = setstate(tag,kind)
state.number = number
end
+commands.definenote = notes.define
+
function notes.save(tag,newkind)
local state = notestates[tag]
if state and not state.saved then
@@ -121,33 +179,10 @@ function notes.restore(tag,forcedstate)
end
end
-function notes.setstate(tag,newkind)
- local state = notestates[tag]
- if trace_notes then
- report_notes("setting state of '%s' from %s to %s",tag,(state and state.kind) or "unset",newkind)
- end
- if not state then
- state = {
- kind = newkind
- }
- notestates[tag] = state
- elseif newkind == "insert" then
- if not state.start then
- state.kind = newkind
- end
- else
- state.kind = newkind
- end
- -- state.start can already be set and will be set when an entry is added or flushed
- return state
-end
-
-function notes.getstate(tag)
- local state = notestates[tag]
- context(state and state.kind or "unknown")
-end
+commands.savenote = notes.save
+commands.restorenote = notes.restore
-function notes.doifcontent(tag)
+local function hascontent(tag)
local ok = notestates[tag]
if ok then
if ok.kind == "insert" then
@@ -160,17 +195,21 @@ function notes.doifcontent(tag)
ok = ok.start
end
end
- commands.doif(ok)
+ return ok and true or false
+end
+
+notes.hascontent = hascontent
+
+function commands.doifnotecontent(tag)
+ commands.doif(hascontent(tag))
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 references.internals[i] -- dependency on references
end
end
@@ -186,7 +225,7 @@ end
notes.internal = internal
notes.ordered = ordered
-function notes.doifonsamepageasprevious(tag)
+local function onsamepageasprevious(tag)
local same = false
local n = getn(tag,n)
local current, previous = get(tag,n), get(tag,n-1)
@@ -194,7 +233,13 @@ function notes.doifonsamepageasprevious(tag)
local cr, pr = current.references, previous.references
same = cr and pr and cr.realpage == pr.realpage
end
- commands.doifelse(same)
+ return same and true or false
+end
+
+notes.doifonsamepageasprevious = onsamepageasprevious
+
+function commands.doifnoteonsamepageasprevious(tag)
+ commands.doifelse(onsamepageasprevious(tag))
end
function notes.checkpagechange(tag) -- called before increment !
@@ -222,13 +267,15 @@ function notes.postpone()
end
for tag, state in next, notestates do
if state.kind ~= "store" then
- notes.setstate(tag,"postpone")
+ setstate(tag,"postpone")
end
end
end
+commands.postponenotes = notes.postpone
+
function notes.setsymbolpage(tag,n,l)
- local l = l or notes.listindex(tag,n)
+ local l = l or listindex(tag,n)
if l then
local p = texcount.realpageno
if trace_notes or trace_references then
@@ -245,41 +292,32 @@ function notes.setsymbolpage(tag,n,l)
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
+commands.setnotesymbolpage = notes.setsymbolpage
-function notes.getsymbolpage(tag,n)
+local function getsymbolpage(tag,n)
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(li)
+ return li
end
-function notes.getnumberpage(tag,n)
+local function getnumberpage(tag,n)
local li = internal(tag,n)
li = li and li.references
li = li and li.realpage or 0
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)
+ return li
end
-function notes.deltapage(tag,n)
+local function getdeltapage(tag,n)
-- 0:unknown 1:textbefore, 2:textafter, 3:samepage
local what = 0
-
--- references.internals[lists.tobesaved[nd].internal]
-
+ -- references.internals[lists.tobesaved[nd].internal]
local li = internal(tag,n)
if li then
local references = li.references
@@ -301,10 +339,18 @@ function notes.deltapage(tag,n)
-- nesting in a vbox
end
end
- context(what)
+ return what
end
-function notes.flush(tag,whatkind,how) -- store and postpone
+notes.getsymbolpage = getsymbolpage
+notes.getnumberpage = getnumberpage
+notes.getdeltapage = getdeltapage
+
+function commands.notesymbolpage(tag,n) context(getsymbolpage(tag,n)) end
+function commands.notenumberpage(tag,n) context(getnumberpage(tag,n)) end
+function commands.notedeltapage (tag,n) context(getdeltapage (tag,n)) end
+
+function commands.flushnotes(tag,whatkind,how) -- store and postpone
local state = notestates[tag]
local kind = state.kind
if kind == whatkind then
@@ -360,12 +406,12 @@ function notes.flush(tag,whatkind,how) -- store and postpone
end
end
-function notes.flushpostponed()
+function commands.flushpostponednotes()
if trace_notes then
report_notes("flushing all postponed notes")
end
for tag, _ in next, notestates do
- notes.flush(tag,"postpone")
+ commands.flushnotes(tag,"postpone")
end
end
diff --git a/tex/context/base/strc-not.mkvi b/tex/context/base/strc-not.mkvi
index 0a57ed878..0a89edf3d 100644
--- a/tex/context/base/strc-not.mkvi
+++ b/tex/context/base/strc-not.mkvi
@@ -21,10 +21,6 @@
% 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
@@ -73,8 +69,6 @@
\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 ]}}]
@@ -123,29 +117,26 @@
\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 }}
+%D The code here is mostly the same as enumersations but we want to keep them
+%D isolated and at some point we might differentiate.
+
+% \installcorenamespace{noteclass}
+
+\unexpanded\def\strc_define_commands_notation#tag#level#parent%
+ {\doifelsenothing{#parent}
+ {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!notation,\c!level=#level]}%
+ \setevalue{\??notation#tag:\s!parent}{\??notation}}%
+ {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!notation,\c!level=#level]}%
+ \setevalue{\??note#tag:\s!parent}{\??note#parent}% see later for \s!note
+ \setevalue{\??notation#tag:\s!parent}{\??notation#parent}}%
+ \setuevalue{\e!next #tag}{\strc_notations_next }%
+ \setuevalue{\c!reset#tag}{\strc_notations_reset }%
+ %setuevalue{\c!set #tag}{\strc_notations_set }%
+ %setuevalue {#tag}{\strc_notations_command{\currentnotation}}%
+ %setuevalue{\e!start#tag}{\strc_notations_start {\currentnotation}{#tag}}%
+ \setuevalue {#tag}{\strc_notations_command{#tag}}%
+ \setuevalue{\e!start#tag}{\strc_notations_start {#tag}{#tag}}% okay?
+ \setuevalue{\e!stop #tag}{\strc_notations_stop }}
\appendtoks
\ifx\currentnotationparent\empty
@@ -179,23 +170,23 @@
\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\p_strc_constructions_title \empty
+\let\p_strc_constructions_number\empty
+
+\unexpanded\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
+ \edef\p_strc_constructions_number{\constructionparameter\c!number}%
+ \ifx\p_strc_constructions_number\v!yes
\settrue\c_strc_constructions_number_state
\iftrialtypesetting
\strc_counters_save\currentconstructionnumber
@@ -204,14 +195,14 @@
\else
\setfalse\c_strc_constructions_number_state
\fi
- \edef\p_title{\constructionparameter\c!title}%
- \ifx\p_title\v!yes
+ \edef\p_strc_constructions_title{\constructionparameter\c!title}%
+ \ifx\p_strc_constructions_title\v!yes
\settrue\c_strc_constructions_title_state
\else
\setfalse\c_strc_constructions_title_state
\fi}
-\setvalue{\??constructionfinalizer\v!notation}%
+\unexpanded\setvalue{\??constructionfinalizer\v!notation}%
{\ifconditional\c_strc_constructions_number_state
\iftrialtypesetting
\strc_counters_restore\currentconstructionnumber
@@ -232,58 +223,58 @@
\let\strc_notations_reset\strc_enumerations_reset
%let\strc_notations_set \strc_enumerations_set
-\unexpanded\def\strc_notations_command#1%
+\unexpanded\def\strc_notations_command#tag%
{\begingroup
- \edef\currentnote{#1}%
- \strc_constructions_initialize{#1}%
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
\strc_notes_synchronize
\ifnotesenabled
\strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
\fi
\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=][]%
+\unexpanded\def\strc_notations_command_nop#title%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#title},\c!bookmark=,\c!list=][]%
\csname\??constructionnotehandler\currentconstructionhandler\endcsname
\strc_constructions_finalize
\normalexpanded{\endgroup\noteparameter\c!next}}
-\unexpanded\def\strc_notations_command_yes[#1]%
- {\doifassignmentelse{#1}\strc_notations_command_assignment\strc_notations_command_argument[#1]}
+\unexpanded\def\strc_notations_command_yes[#optional]%
+ {\doifassignmentelse{#optional}\strc_notations_command_assignment\strc_notations_command_argument[#optional]}
-\unexpanded\def\strc_notations_command_assignment[#1]%
- {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1][]%
+\unexpanded\def\strc_notations_command_assignment[#settings]%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#settings][]%
\csname\??constructionnotehandler\currentconstructionhandler\endcsname
\strc_constructions_finalize
\normalexpanded{\endgroup\noteparameter\c!next}}
-\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=][]%
+\unexpanded\def\strc_notations_command_argument[#reference]#title%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#reference},\c!title={#title},\c!bookmark=,\c!list=][]%
\csname\??constructionnotehandler\currentconstructionhandler\endcsname
\strc_constructions_finalize
\normalexpanded{\endgroup\noteparameter\c!next}}
-\unexpanded\def\strc_notations_start#1#2%
+\unexpanded\def\strc_notations_start#tag#stoptag%
{\begingroup
- \edef\currentnote{#1}%
- \strc_constructions_initialize{#1}%
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
\strc_notes_synchronize
\ifnotesenabled
\strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
\fi
\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}}}%
+ {\def\noexpand\strc_pickup_yes[##1]##2\csname\e!stop#stoptag\endcsname{\strc_notations_command_yes[##1]{##2}}%
+ \def\noexpand\strc_pickup_nop ##1\csname\e!stop#stoptag\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=][]%
+\unexpanded\def\strc_notations_start_yes[#reference]#title%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#reference},\c!title={#title},\c!bookmark=,\c!list=][]%
\csname\??constructionnotehandler\currentconstructionhandler\endcsname
\strc_constructions_finalize
\normalexpanded{\endgroup\noteparameter\c!next}}
-\unexpanded\def\strc_notations_start_nop#1%
- {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]%
+\unexpanded\def\strc_notations_start_nop#title%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#title},\c!bookmark=,\c!list=][]%
\csname\??constructionnotehandler\currentconstructionhandler\endcsname
\strc_constructions_finalize
\normalexpanded{\endgroup\noteparameter\c!next}}
@@ -296,10 +287,10 @@
%D level of indirectness. This way notations don't bark on undefined
%D macros when used in combination.
-\setvalue{\??constructionnotehandler\v!notation}%
+\unexpanded\setvalue{\??constructionnotehandler\v!notation}%
{\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname}
-\setvalue{\??constructionnotehandler\v!notation:}% empty case
+\unexpanded\setvalue{\??constructionnotehandler\v!notation:}% empty case
{[\currentconstructionhandler:\currentconstruction]}
%D Here is a simple renderer for notes
@@ -371,51 +362,65 @@
%D Insertions are part of notes.
-\installcorenamespace{noteinsertion}
-
-\def\currentnoteins{\csname\??noteinsertion\currentnote\endcsname}
+% \installcorenamespace{noteinsertion}
+
+\def\currentnoteinsertion {\noteparameter\s!insert}
+\def\currentnoteinsertionnumber{\namedinsertionnumber{\noteparameter\s!insert}}
+
+% \appendtoks
+% \doifinsertionelse\currentnote
+% \donothing
+% {\defineinsertion[\currentnote]% could be an option
+% \normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}}%
+% \letnoteparameter\s!insert\currentnote
+% \ctxcommand{definenote("\currentnote","insert",\number\currentnoteinsertionnumber)}%
+% \ifx\currentnoteparent\empty
+% \definenotation[\currentnote][\c!type=\v!note]%
+% \else
+% \definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]%
+% \fi
+% \to \everydefinenote
\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
+ \doifinsertionelse\currentnote
+ \donothing
+ {\defineinsertion[\currentnote]% could be an option
+ \normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}}%
+ \letnoteparameter\s!insert\currentnote
\definenotation[\currentnote][\c!type=\v!note]%
\else
+ \setexpandednoteparameter\s!insert{\namednoteparameter\currentnoteparent\s!insert}%
\definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]%
\fi
+ \ctxcommand{definenote("\currentnote","insert",\number\currentnoteinsertionnumber)}%
\to \everydefinenote
-% maybe we will share this at some point
-
-%%%%%%%%%%% BEGIN TODO (SEE ENUMERATIONS) %%%%%%%%%%%%%%%
+% maybe we will share this at some point:
\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
+\def\strc_notes_setup_counter#tag%
+ {\edef\v_strc_note_counter_name{#tag}% 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}}
+\def\strc_notes_define_counter#tag% todo: fast inheritance (was mainparameter
+ {\definecounter[#tag]%
+ \strc_notes_setup_counter{#tag}}
\appendtoks
\strc_counter_setup_using_parameter\v_strc_note_counter_name\notationparameter
\to \everysetupnotecounter
\appendtoks
- \strc_notes_setup_counter\currentnotation
+ \ifx\currentnotation\empty \else
+ \strc_notes_setup_counter\currentnotation
+ \fi
\to \everysetupnotation
-%%%%%%%%%%% END TODO (SEE ENUMERATIONS) %%%%%%%%%%%%%%%
-
-% \setvalue{\??constructionstarthandler\v!notation}%
-% {\csname\??constructionstarthandler\v!construction\endcsname}
+% so far
%expandafter\let\csname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!enumeration\endcsname
\expandafter\let\csname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!construction\endcsname % no par mess
@@ -423,35 +428,42 @@
\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%
+\unexpanded\setvalue{\??constructionmainhandler\v!notation}#following%
{\iftrialtypesetting \else
\begingroup
\currentconstructionsynchronize
\attribute\destinationattribute\currentconstructionattribute\relax % todo, whole text
\signalcharacter
\endgroup
- \fi#1}
+ \fi#following}
-\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text
+\unexpanded\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text
{\ifnotesenabled
- \let\currentnote\currentconstructionmain % do be done elsewhere
+ % do be done elsewhere
+ %
+ %let\currentnote\currentconstructionmain
+ \let\currentnote\currentconstruction % else wrong inheritance
+ %
\iftrialtypesetting
\strc_notes_inject_dummy
\else
\begingroup
- \edef\currentnotenumber{\ctxlua{structures.notes.store("\currentnote",\currentconstructionlistentry)}}%
+ \edef\currentnotenumber{\ctxcommand{storenote("\currentnote",\currentconstructionlistentry)}}%
\settrue\processingnote
\ifconditional\c_strc_notes_skip
- \globallet\lastnotesymbol\strc_notes_inject_symbol
+ \globallet\lastnotesymbol\strc_notes_inject_symbol_nop
+ \ifconditional\c_strc_notes_delayed
+ \strc_notes_inject_symbol_snc
+ \fi
\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
+ \strc_notes_inject_symbol_yes
\else
\unskip\unskip
- \globallet\lastnotesymbol\strc_notes_inject_symbol
+ \globallet\lastnotesymbol\strc_notes_inject_symbol_yes
\fi
\fi
\ifconditional\postponingnotes % todo: per note class
@@ -514,7 +526,7 @@
\endcsname}
\setvalue{\??noteinteractioninline\v!yes}%
- {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getnumberpage("\currentnote",\currentnotenumber)})}%
+ {\strc_references_get_simple_page_reference{page(\ctxcommand{notenumberpage("\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}
@@ -531,8 +543,10 @@
\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
+% page(...) : we could have a dedicated one
+
\setvalue{\??noteinteractiondisplay\v!yes}%
- {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getsymbolpage("\currentnote",\currentnotenumber)})}%
+ {\strc_references_get_simple_page_reference{page(\ctxcommand{notesymbolpage("\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
@@ -545,7 +559,7 @@
\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)})}%
+ {\strc_references_get_simple_page_reference{page(\ctxcommand{notesymbolpage("\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}%
@@ -554,7 +568,7 @@
\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)})}%
+ {\strc_references_get_simple_page_reference{page(\ctxcommand{notesymbolpage("\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}%
@@ -567,19 +581,19 @@
\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%
+\unexpanded\def\strc_notes_set_style_color_inline_yes#style#color%
+ {\usenotestyleandcolor#style#color%
\iflocation\strc_notes_set_style_color_special\fi}
-\unexpanded\def\strc_notes_set_style_color_display_yes#1#2%
- {\usenotationstyleandcolor#1#2%
+\unexpanded\def\strc_notes_set_style_color_display_yes#style#color%
+ {\usenotationstyleandcolor#style#color%
\iflocation\strc_notes_set_style_color_special\fi}
\def\strc_notes_set_style_color_special
{\iftrialtypesetting
% keep
\else\ifx\currentcolorparameter\empty
- \scratchcounter\ctxlua{structures.notes.deltapage("\currentnote",\currentnotenumber)}\relax % todo calculate once
+ \scratchcounter\ctxcommand{notedeltapage("\currentnote",\currentnotenumber)}\relax % todo calculate once
\setlocationcolorspecified\scratchcounter
\fi\fi}
@@ -598,7 +612,7 @@
% 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
+ {\ifcase\ctxcommand{notedeltapage("\currentnote",\currentnotenumber)}\relax
% unknown
\or
% same page
@@ -610,10 +624,19 @@
\unexpanded\def\strc_notes_register_note_page % called more often than needed
{\iftrialtypesetting \else
- \normalexpanded{\noexpand\ctxlatelua{structures.notes.setsymbolpage("\currentnote",\currentnotenumber)}}%
+ \normalexpanded{\noexpand\ctxlatecommand{setnotesymbolpage("\currentnote",\currentnotenumber)}}%
\fi}
-\unexpanded\def\strc_notes_inject_symbol
+\unexpanded\def\strc_notes_inject_symbol_yes
+ {\strc_notes_inject_symbol_indeed\conditionaltrue}
+
+\unexpanded\def\strc_notes_inject_symbol_nop
+ {\strc_notes_inject_symbol_indeed\conditionalfalse}
+
+\unexpanded\def\strc_notes_inject_symbol_snc
+ {\currentconstructionsynchronize} % this flushes the data to the list
+
+\unexpanded\def\strc_notes_inject_symbol_indeed#synchronize%
{\removeunwantedspaces
\doifitalicelse\/\donothing % Charles IV \footnote{the fourth}
\ifdim\lastkern=\notesignal
@@ -622,7 +645,9 @@
\fi
\nobreak
\begingroup
- \currentconstructionsynchronize % this flushes the data to the list
+ \ifconditional#synchronize\relax
+ \strc_notes_inject_symbol_snc % this flushes the data to the list
+ \fi
\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
@@ -646,7 +671,7 @@
\strc_notes_inject_separator
\fi
\nobreak
- \hbox to .5em{}%
+ \hbox to .5\emwidth{}%
\globallet\lastnotesymbol\relax}
\unexpanded\def\strc_notes_inject_separator % patch by WS due to request on list
@@ -751,8 +776,8 @@
\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}%
+\unexpanded\def\strc_notes_process#action% argument is a \macro that uses \currentnote
+ {\def\strc_notes_process_list##1{\edef\currentnote{##1}\let\currentdescription\currentnote#action}%
\the\t_strc_notes}
\newtoks\everychecknote % just before a note is typeset
@@ -805,8 +830,8 @@
{\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}
+\def\strc_notes_set_rule_step#alternative%
+ {\csname\??noterule\ifcsname\??noterule#alternative\endcsname#alternative\else\s!unknown\fi\endcsname}
\setvalue{\??noterule\v!command}{\letcurrentnoterulecommand\currentnoterulecommandcommand}
\setvalue{\??noterule \v!on}{\letcurrentnoterulecommand\currentnoterulecommandnormal}
@@ -857,7 +882,7 @@
\ifx\p_factor\empty \else
\ifnum\p_factor<\zerocount \else
% \global
- \count\currentnoteins\p_factor % new: global
+ \count\currentnoteinsertionnumber\p_factor % new: global
\fi
\fi}
@@ -869,50 +894,81 @@
\installcorenamespace{notelocationvariant}
\installcorenamespace{notepositionvariant}
-\installcorenamespace{notedelayed}
+\installcorenamespace{notedelayedvariant}
\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}
+\unexpanded\def\strc_notes_set_delayed_yes{\settrue \c_strc_notes_delayed}
+\unexpanded\def\strc_notes_set_delayed_nop{\setfalse\c_strc_notes_delayed}
+
+\setvalue{\??notelocation\v!page }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page}
+\setvalue{\??notelocation\v!columns }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_columns}
+\setvalue{\??notelocation\v!lastcolumn }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_lastcolumn}
+\setvalue{\??notelocation\v!firstcolumn}{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_firstcolumn}
+\setvalue{\??notelocation\v!none }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_none}
+\setvalue{\??notelocation\v!text }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes
+ \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_text}
\setvalue{\??notelocation\v!high }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_high}
\setvalue{\??notelocation\v!bottom }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom}
-\letvalue{\??notedelayed\v!page }\setfalse
-\letvalue{\??notedelayed\v!columns }\setfalse
-\letvalue{\??notedelayed\v!lastcolumn }\setfalse
-\letvalue{\??notedelayed\v!firstcolumn }\setfalse
-\letvalue{\??notedelayed\v!none }\settrue
-\letvalue{\??notedelayed\v!text }\settrue
+\setvalue{\??notedelayedvariant \??notedelayedvariant }{\strc_notes_set_delayed_nop} % not let
+\setvalue{\??notepositionvariant\??notepositionvariant}{\strc_notes_set_position_bottom} % not let
+\setvalue{\??notelocationvariant\??notelocationvariant}{\strc_notes_set_location_page} % not let
\unexpanded\def\strc_notes_set_delayed
- {\ifcsname\??notedelayed\currentnote\endcsname
- \csname\??notedelayed\currentnote\endcsname\c_strc_notes_delayed
- \else
- \setfalse\c_strc_notes_delayed
- \fi}
+ {\csname\??notedelayedvariant
+ \ifcsname\??notedelayedvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notedelayedvariant
+ \fi
+ \endcsname}
+
+% \let\strc_notes_set_delayed_yes\truecondition
+% \let\strc_notes_set_delayed_nop\falsecondition
+%
+% \def\c_strc_notes_delayed
+% {\csname\??notedelayedvariant
+% \ifcsname\??notedelayedvariant\currentnote\endcsname
+% \currentnote
+% \else
+% \??notedelayedvariant
+% \fi
+% \endcsname}
+
+\unexpanded\def\strc_notes_set_position
+ {\csname\??notepositionvariant
+ \ifcsname\??notepositionvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notepositionvariant
+ \fi
+ \endcsname}
\unexpanded\def\strc_notes_set_location
- {\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page
- \letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom
- \setfalse\c_strc_notes_delayed
- \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
- \ifcsname\??notedelayed#1\endcsname
- \csname\??notedelayed#1\endcsname\c_strc_notes_delayed
- \fi}
+ {\csname\??notelocationvariant
+ \ifcsname\??notelocationvariant\currentnote\endcsname
+ \currentnote
+ \else
+ \??notelocationvariant
+ \fi
+ \endcsname}
+
+\unexpanded\def\strc_notes_set_variants
+ {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}}
+
+\unexpanded\def\strc_notes_set_location_step#alternative% the insert related one
+ {\ifcsname\??notelocation#alternative\endcsname\csname\??notelocation#alternative\endcsname\fi}
\appendtoks
- \strc_notes_set_location
+ \strc_notes_set_variants
+ \strc_notes_set_delayed
\to \everysynchronizenote
\newskip \s_strc_notes_distance % we need to implement stretch
@@ -940,9 +996,10 @@
{\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}
+ \page_inserts_set_location\currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]%
+ \global\count\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
\def\strc_notes_set_location_columns
{\setfalse\c_strc_notes_delayed
@@ -951,33 +1008,38 @@
\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}
+ \page_inserts_set_location\currentnoteinsertion\v!columns % \setupinsertion[\currentnote][\c!location=\v!columns]%
+ \global\count\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
-\def\strc_notes_set_location_firstcolumn
+\def\strc_notes_set_location_somecolumn#whatcolumn%
{\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}
+ \page_inserts_set_location\currentnoteinsertion#whatcolumn% \setupinsertion[\currentnote][\c!location=#whatcolumn]%
+ \global\count\currentnoteinsertionnumber\plusthousand
+ \global\dimen\currentnoteinsertionnumber\ifnotelimit\noteparameter\c!height\else\maxdimen\fi
+ \global\skip \currentnoteinsertionnumber\s_strc_notes_distance}
-\let\strc_notes_set_location_lastcolumn\strc_notes_set_location_firstcolumn
+\def\strc_notes_set_location_firstcolumn{\strc_notes_set_location_somecolumn\v!firstcolumn}
+\def\strc_notes_set_location_lastcolumn {\strc_notes_set_location_somecolumn\v!lastcolumn }
\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes)
{\settrue\c_strc_notes_delayed
- \ctxlua{structures.notes.setstate("\currentnote","store")}%
- \global\dimen\currentnoteins\maxdimen
- \global\count\currentnoteins\zerocount
- \global\skip \currentnoteins\zeropoint}
+ \ctxcommand{setnotestate("\currentnote","store")}%
+ \page_inserts_set_location\currentnoteinsertion\v!text % \setupinsertion[\currentnote][\c!location=\v!text]%
+ \global\count\currentnoteinsertionnumber\zerocount
+ \global\dimen\currentnoteinsertionnumber\maxdimen
+ \global\skip \currentnoteinsertionnumber\zeropoint}
\let\strc_notes_set_location_none\strc_notes_set_location_text
\def\strc_notes_set_properties
{\strc_notes_set_columns
\strc_notes_set_distance
- \csname\??notelocationvariant\currentnote\endcsname}
+ \strc_notes_set_location
+ \strc_notes_set_delayed}
\let\strc_notes_set_position_high\relax
@@ -993,8 +1055,8 @@
\newconditional\c_notes_bottom_present
\def\strc_notes_check_if_bottom_present_indeed % in otr !
- {\ifvoid\currentnoteins\else
- \csname\??notepositionvariant\currentnote\endcsname
+ {\ifvoid\currentnoteinsertionnumber\else
+ \strc_notes_set_position
\fi}
\def\strc_notes_check_if_bottom_present_step
@@ -1105,39 +1167,39 @@
\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\setnote [#tag]{\getvalue{#tag}}
+\unexpanded\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\getvalue{#tag}}
-\unexpanded\def\handlenoteinsert#1#2% tg, id
+\unexpanded\def\handlenoteinsert#tag#id%
{\begingroup
- \edef\currentnote{#1}%
- \strc_constructions_initialize{#1}%
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
\strc_notes_synchronize
\the\everybeforenoteinsert
- \insert\currentnoteins\bgroup
+ \insert\currentnoteinsertionnumber\bgroup
\the\everyinsidenoteinsert\relax
\doprocesslocalsetups{\noteparameter\c!setups}% experimental
\doifelse{\noteparameter\c!paragraph}\v!yes
{\nointerlineskip
\startvboxtohbox
- \handlenoteitself{#1}{#2}%
+ \handlenoteitself{#tag}{#id}%
% add some slack
\stopvboxtohbox}
- {\handlenoteitself{#1}{#2}}%
+ {\handlenoteitself{#tag}{#id}}%
\egroup
\the\everyafternoteinsert
\endgroup}
-\unexpanded\def\betweennoteitself#1% tg
- {\edef\currentnote{#1}%
+\unexpanded\def\betweennoteitself#tag%
+ {\edef\currentnote{#tag}%
\doif{\noteparameter\c!paragraph}\v!yes\strc_notes_between_paragraphs}
-\unexpanded\def\handlenoteitself#1#2% tg, id
- {\edef\currentnotenumber{#2}%
- \edef\currentnote{#1}%
- \strc_constructions_initialize{#1}%
+\unexpanded\def\handlenoteitself#tag#id%
+ {\edef\currentnotenumber{#id}%
+ \edef\currentnote{#tag}%
+ \strc_constructions_initialize{#tag}%
\strc_notes_synchronize
- \edef\currentconstructionlistentry{\ctxlua{tex.write(structures.notes.listindex("#1",#2))}}% index in list cache
+ \edef\currentconstructionlistentry{\ctxcommand{notelistindex("\currentnote",#id)}}% index in list cache
% as we can have collected notes (e.g. in tables) we need to recover
% \currentdescriptionattribute and \currentdescriptionsynchronize
%
@@ -1157,7 +1219,7 @@
% \endgroup
}
-\unexpanded\def\strc_notes_inject_text
+\unexpanded\def\strc_notes_inject_text % hm main?
{\ctxcommand{savedlisttitle("\currentconstructionmain",\currentconstructionlistentry)}}
\let\startpushnote\relax
@@ -1216,14 +1278,14 @@
\def\strc_notes_place_inserts
{\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed
\ifconditional\c_strc_notes_delayed \else
- \ifdim\ht\currentnoteins>\zeropoint % or a faster delayed test
+ \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test
\strc_notes_place_inserts_indeed
\fi
\fi}
\def\strc_notes_place_inserts_indeed
{\relax
- \ifdim\ht\currentnoteins>\zeropoint
+ \ifdim\ht\currentnoteinsertionnumber>\zeropoint
\endgraf
\ifvmode
\whitespace
@@ -1271,13 +1333,11 @@
\fi}
\def\strc_notes_flush_inserts_normal
- {%\iftrialtypesetting\copy\else\box\fi\currentnoteins
- \strc_notes_flush_global
+ {\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}
@@ -1293,18 +1353,15 @@
{\doifelse{\noteparameter\c!paragraph}\v!yes
{\vbox
{\beginofshapebox
- \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins
+ \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber
\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
+ \donothing \donothing \donothing % get rid of penalties etc
\innerflushshapebox
\convertvboxtohbox}}
- {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins}}
+ {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber}}
%D Supporting end notes is surprisingly easy. Even better, we
%D can combine this feature with solving the common \TEX\
@@ -1338,21 +1395,21 @@
% we need a proper state: normal, postponing, flushing
-\def\postponenotes
+\unexpanded\def\postponenotes
{\ifconditional\postponingnotes\else
\global\settrue\postponingnotes
\global\let\flushnotes\doflushnotes
- \ctxlua{structures.notes.postpone()}%
+ \ctxcommand{postponenotes()}%
\fi}
\let\flushnotes\relax
-\def\doflushnotes
+\unexpanded\def\doflushnotes
{\ifconditional\postponingnotes
\begingroup
\let\flushnotes \relax
\let\postponenotes\relax
- \ctxlua{structures.notes.flushpostponed()}% this also resets the states !
+ \ctxcommand{flushpostponednotes()}% this also resets the states !
\global\setfalse\postponednote
\global\setfalse\postponingnotes
\global\let\flushnotes\relax
@@ -1382,8 +1439,8 @@
\unexpanded\def\startlocalnotes
{\dosingleempty\strc_notes_local_start}
-\def\strc_notes_local_start[#1]%
- {\def\localnoteslist{#1}%
+\def\strc_notes_local_start[#list]% grouping ? (we used to have a second argument ... settings)
+ {\def\localnoteslist{#list}%
\settrue\inlocalnotes
\processcommacommand[\localnoteslist]\strc_notes_local_start_step}
@@ -1391,29 +1448,35 @@
{\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")}}
+\let\p_strc_notes_continue\empty
-\def\strc_notes_local_stop_step#1%
- {\doifnot{\noteparameter\c!continue}\v!yes
- {\strc_counters_restore{#1}}%
- \ctxlua{structures.notes.restore("#1")}}
+\def\strc_notes_local_start_step#tag%
+ {\p_strc_notes_continue{\noteparameter\c!continue}%
+ \ifx\p_strc_notes_continue\v!yes \else
+ \strc_counters_save{#tag}%
+ \strc_counters_reset{#tag}%
+ \fi
+ \ctxcommand{savenote("#tag","store")}}
+
+\def\strc_notes_local_stop_step#tag%
+ {\p_strc_notes_continue{\noteparameter\c!continue}%
+ \ifx\p_strc_notes_continue\v!yes \else
+ \strc_counters_restore{#tag}%
+ \fi
+ \ctxcommand{restorenote("#tag")}}
\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[#tag][#settings]%
+ {\doif{\ctxcommand{getnotestate("#tag")}}{store}{\strc_notes_local_place_indeed{#settings}{#tag}}}
-\def\strc_notes_local_place_indeed#1#2% settings note
+\def\strc_notes_local_place_indeed#settings#tag%
{\begingroup
- \edef\currentnote{#2}% is already set?
+ \edef\currentnote{#tag}% 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
+ \setupcurrentnote[#settings]% later we set height etc for framed
\strc_notes_place_local_alternative
\strc_notes_set_properties % restore globals (if needed)
\endgroup
@@ -1460,19 +1523,19 @@
\unexpanded\def\placenotes
{\dodoubleempty\strc_notes_place}
-\def\strc_notes_place[#1][#2]%
- {\processcommalist[#1]{\strc_notes_place_indeed{#2}}}
+\def\strc_notes_place[#list][#settings]%
+ {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}}
-\def\strc_notes_place_indeed#1#2% settings note
- {\edef\currentnote{#2}% grouping ?
- \doifelse{\ctxlua{structures.notes.getstate("#2")}}{store}
+\def\strc_notes_place_indeed#settings#tag% settings note
+ {\edef\currentnote{#tag}% grouping ?
+ \doifelse{\ctxcommand{getnotestate("#tag")}}{store}
\strc_notes_local_place_indeed
\strc_notes_global_place_indeed
- {#1}{#2}}
+ {#settings}{#tag}}
-\def\strc_notes_global_place_indeed#1#2%
+\def\strc_notes_global_place_indeed#settings#tag%
{\begingroup
- \setupnote[#2][#1]%
+ \setupnote[#tag][#settings]%
\strc_notes_place_inserts
\endgroup
\the\everysetupnote} % to be checked .. synchronize
@@ -1481,11 +1544,11 @@
\installcorenamespace{notealternative}
-\unexpanded\def\installnotealternative#1#2%
- {\setvalue{\??notealternative#1}{#2}}
+\unexpanded\def\installnotealternative#alternative#command%
+ {\setvalue{\??notealternative#alternative}{#command}}
-\unexpanded\def\doifnotescollected#1%
- {\ctxlua{structures.notes.doifcontent("#1")}}
+\unexpanded\def\doifnotescollected#tag%
+ {\ctxcommand{doifnotecontent("#tag")}}
\def\strc_notes_place_local_alternative % will be a setup (wrapper)
{\doifnotescollected\currentnote
@@ -1512,8 +1575,7 @@
% setups ?
-% \def\flushlocalnotes#1{\ctxlua{structures.notes.flush("#1","store")}}
-\def\flushlocalnotes#1{\ctxlua{structures.notes.flush("#1","store","\noteparameter\c!criterium")}}
+\def\flushlocalnotes#tag{\ctxcommand{flushnotes("#tag","store","\noteparameter\c!criterium")}}
\installnotealternative \v!none
{\flushlocalnotes\currentnote}
@@ -1569,58 +1631,62 @@
\strc_notes_process\strc_notes_check_presence}
\def\strc_notes_check_presence
- {\ifdim\ht\currentnoteins>\zeropoint
+ {\ifdim\ht\currentnoteinsertionnumber>\zeropoint
\notespresenttrue
\fi}
%D \macros
%D {fakenotes}
- % used in page-mul
+ % used in page-mul
+
+ \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi
- \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\@@kln} \fi
+ \unexpanded\def\fakenotes
+ {\ifhmode\endgraf\fi\ifvmode
+ \calculatetotalclevernoteheight
+ \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
+ \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}
- \unexpanded\def\fakepagenotes
- {\ifhmode\endgraf\fi\ifvmode
- \calculatetotalpagenoteheight
- \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
- \fi}
+ % used in page-not but not yet ok
- \newdimen\totalnoteheight
+ \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}
+ \unexpanded\def\additionaltotalnoteheight#insert% temp hacks anyway
+ {\dimexpr
+ \ifdim\ht#insert>\zeropoint
+ \ifcase\count#insert %
+ \zeropoint
+ \else % todo: divide by count
+ \ht#insert+\skip#insert% hm, no stretch but a dimen anyway
+ \fi
+ \else
+ \zeropoint
+ \fi
+ \relax}
- \def\docalculatetotalnoteheight
- {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! !
- \doaddtototalnoteheight\currentnoteins
- \else
- % \doaddtototalnoteheight\currentbackupnoteins
- \fi}
+ \def\docalculatetotalnoteheight
+ {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! !
+ \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
+ \fi}
- \def\docalculatetotalclevernoteheight
- {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! !
- \doaddtototalnoteheight\currentnoteins
- \fi}
+ \def\docalculatetotalclevernoteheight
+ {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! !
+ \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}%
+ \fi}
- \def\docalculatetotalpagenoteheight
- {\doaddtototalnoteheight\currentnoteins}
+ \def\docalculatetotalpagenoteheight
+ {\advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}}
- \def\calculatetotalnoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight}
- \def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight}
- \def\calculatetotalpagenoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalpagenoteheight}
+ \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
@@ -1644,7 +1710,7 @@
%D \stoptyping
% \def\dosynchronizenotes
-% {\ifvoid\currentnoteins\else\insert\currentnoteins{\unvbox\currentnoteins}\fi}
+% {\ifvoid\currentnoteinsertionnumber\else\insert\currentnoteinsertionnumber{\unvbox\currentnoteinsertionnumber}\fi}
%
% \def\synchronizenotes
% {\strc_notes_process\dosynchronizenotes}
@@ -1679,8 +1745,19 @@
\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}
+\def\strc_notes_place_footnotes[#list][#settings]%
+ {\ifsecondargument
+ \placenotes[#list][#settings,\c!height=\textheight]%
+ \else
+ \placenotes[#list][\c!height=\textheight]%
+ \fi}
+
+\def\strc_notes_place_local_footnotes[#list][#settings]%
+ {\ifsecondargument
+ \placelocalnotes[#list][#settings,\c!height=\textheight]%
+ \else
+ \placelocalnotes[#list][\c!height=\textheight]%
+ \fi}
%D Goodies:
%D
@@ -1690,7 +1767,7 @@
%D }
%D \stoptyping
-\def\doifnoteonsamepageelse[#1]{\ctxlua{structures.notes.doifonsamepageasprevious("#1")}}
+\def\doifnoteonsamepageelse[#tag]{\ctxcommand{doifnoteonsamepageasprevious("#tag")}}
%D New trickery:
@@ -1711,15 +1788,15 @@
\unexpanded\def\notesymbol
{\dodoubleempty\strc_notes_symbol}
-\def\strc_notes_symbol[#1][#2]%
+\def\strc_notes_symbol[#tag][#reference]%
{\dontleavehmode
\begingroup
- \edef\currentnote{#1}%
+ \edef\currentnote{#tag}%
\usenotestyleandcolor\c!textstyle\c!textcolor
\ifnotesenabled
\ifsecondargument
\unskip
- \noteparameter\c!textcommand{\in[#2]}% command here?
+ \noteparameter\c!textcommand{\in[#reference]}% command here?
\else
\noteparameter\c!textcommand\lastnotesymbol % check if command double
\fi
@@ -1729,30 +1806,30 @@
\unexpanded\def\note
{\dodoubleempty\strc_notes_note}
-\def\strc_notes_note[#1][#2]%
+\def\strc_notes_note[#tag][#reference]%
{\ifsecondargument
- \strc_notes_symbol[#1][#2]%
+ \strc_notes_symbol[#tag][#reference]%
\else
\secondargumenttrue
- \strc_notes_symbol[\v!footnote][#1]%
+ \strc_notes_symbol[\v!footnote][#tag]%
\fi}
% will be redone if needed
%
-% \def\ownnotesymbol#1% #1 gets number passed
-% {\executeifdefined{\??notesymbol\currentnote}\empty}
+% \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\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}}
+% \unexpanded\def\ownnote[#1]#2#3#4%
+% {\setnotesymbol[#1]{#2}{#3}%
+% \setnotetext [#1]{#4}}
%
-% \defineconversion
-% [ownnote]
-% [\ownnotesymbol]
+% \defineconversion
+% [ownnote]
+% [\ownnotesymbol]
\protect \endinput
diff --git a/tex/context/base/strc-num.lua b/tex/context/base/strc-num.lua
index 0715a9e49..b82132a00 100644
--- a/tex/context/base/strc-num.lua
+++ b/tex/context/base/strc-num.lua
@@ -6,12 +6,13 @@ if not modules then modules = { } end modules ['strc-num'] = {
license = "see context related readme files"
}
--- 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 texcount = tex.count
+local texcount, texsetcount = tex.count, tex.setcount
+
+-- Counters are managed here. They can have multiple levels which makes it easier to synchronize
+-- them. Synchronization is sort of special anyway, as it relates to document structuring.
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -26,8 +27,23 @@ local counters = structures.counters
local documents = structures.documents
local variables = interfaces.variables
-
--- state: start stop none reset
+local v_start = variables.start
+local v_page = variables.page
+local v_reverse = variables.reverse
+local v_first = variables.first
+local v_next = variables.next
+local v_previous = variables.previous
+local v_prev = variables.prev
+local v_last = variables.last
+----- v_no = variables.no
+local v_backward = variables.backward
+local v_forward = variables.forward
+----- v_subs = variables.subs or "subs"
+
+-- states: start stop none reset
+
+-- specials are used for counters that are set and incremented in special ways, like
+-- pagecounters that get this treatment in the page builder
counters.specials = counters.specials or { }
local counterspecials = counters.specials
@@ -66,54 +82,83 @@ end
job.register('structures.counters.collected', tobesaved, initializer, finalizer)
-local function constructor(t,s,name,i) -- variables ?
- if s == "last" then
+local constructor = { -- maybe some day we will provide an installer for more variants
+
+ last = function(t,name,i)
local cc = collected[name]
- t.stop = (cc and cc[i] and cc[i][t.range]) or 0 -- stop is available for diagnostics purposes only
+ local stop = (cc and cc[i] and cc[i][t.range]) or 0 -- stop is available for diagnostics purposes only
+ t.stop = stop
if t.offset then
- return t.stop - t.step
+ return stop - t.step
else
- return t.stop
+ return stop
end
- elseif s == "first" then
- if t.start > 0 then
- return t.start -- brrr
+ end,
+
+ first = function(t,name,i)
+ local start = t.start
+ if start > 0 then
+ return start -- brrr
elseif t.offset then
- return t.start + t.step + 1
+ return start + t.step + 1
else
- return t.start + 1
+ return start + 1
end
- elseif s == "prev" or s == "previous" then
+ end,
+
+ prev = function(t,name,i)
return max(t.first,t.number-1) -- todo: step
- elseif s == "next" then
+ end,
+
+ previous = function(t,name,i)
+ return max(t.first,t.number-1) -- todo: step
+ end,
+
+ next = function(t,name,i)
return min(t.last,t.number+1) -- todo: step
- elseif s == "backward" then
+ end,
+
+ backward =function(t,name,i)
if t.number - 1 < t.first then
return t.last
else
return t.previous
end
- elseif s == "forward" then
+ end,
+
+ forward = function(t,name,i)
if t.number + 1 > t.last then
return t.first
else
return t.next
end
- elseif s == "subs" then
+ end,
+
+ subs = function(t,name,i)
local cc = collected[name]
t.subs = (cc and cc[i+1] and cc[i+1][t.range]) or 0
return t.subs
- else
- return nil -- was 0, but that is fuzzy in testing for e.g. own
- end
+ end,
+
+}
+
+local function dummyconstructor(t,name,i)
+ return nil -- was 0, but that is fuzzy in testing for e.g. own
end
+setmetatableindex(constructor,function(t,k)
+ if trace_counters then
+ report_counters("unknown constructor %q",tostring(k))
+ end
+ return dummyconstructor
+end)
+
local function enhance()
for name, cd in next, counterdata do
local data = cd.data
for i=1,#data do
local ci = data[i]
- setmetatableindex(ci, function(t,s) return constructor(t,s,name,i) end)
+ setmetatableindex(ci, function(t,s) return constructor[s](t,name,i) end)
end
end
enhance = nil
@@ -126,7 +171,7 @@ local function allocate(name,i) -- can be metatable
level = 1,
-- block = "", -- todo
numbers = nil,
- state = variables.start, -- true
+ state = v_start, -- true
data = { },
saved = { },
}
@@ -145,7 +190,7 @@ local function allocate(name,i) -- can be metatable
offset = false,
stop = 0, -- via metatable: last, first, stop only for tracing
}
- setmetatableindex(ci, function(t,s) return constructor(t,s,name,i) end)
+ setmetatableindex(ci, function(t,s) return constructor[s](t,name,i) end)
cd[i] = ci
tobesaved[name][i] = { }
else
@@ -164,12 +209,12 @@ local function savevalue(name,i)
local cs = tobesaved[name][i]
local cc = collected[name]
if trace_counters then
- report_counters("saving value %s of counter named %s",cd.number,name)
+ report_counters("saving, counter: %s, value: %s",name,cd.number)
end
local cr = cd.range
local old = (cc and cc[i] and cc[i][cr]) or 0
local number = cd.number
- if cd.method == variables.page then
+ if cd.method == v_page then
-- we can be one page ahead
number = number - 1
end
@@ -186,8 +231,8 @@ function counters.define(specification)
if name and name ~= "" then
-- todo: step
local d = allocate(name,1)
- d.start = specification.start
- d.state = variables.start or ""
+ d.start = tonumber(specification.start) or 0
+ d.state = v_state or ""
local counter = specification.counter
if counter and counter ~= "" then
d.counter = counter -- only for special purposes, cannot be false
@@ -202,18 +247,15 @@ end
function counters.compact(name,level,onlynumbers)
local cd = counterdata[name]
---~ print(name,cd)
if cd then
local data = cd.data
local compact = { }
for i=1,level or #data do
local d = data[i]
---~ print(name,i,d.number)
if d.number ~= 0 then
compact[i] = (onlynumbers and d.number) or d
end
end
---~ print(table.serialize(compact))
return compact
end
end
@@ -246,65 +288,76 @@ function counters.subs(name,n)
return counterdata[name].data[n].subs or 0
end
-function counters.setvalue(name,tag,value)
+local function setvalue(name,tag,value)
local cd = counterdata[name]
if cd then
cd[tag] = value
end
end
+counters.setvalue = setvalue
+
function counters.setstate(name,value) -- true/false
value = variables[value]
if value then
- counters.setvalue(name,"state",value)
+ setvalue(name,"state",value)
end
end
function counters.setlevel(name,value)
- counters.setvalue(name,"level",value)
+ setvalue(name,"level",value)
end
function counters.setoffset(name,value)
- counters.setvalue(name,"offset",value)
+ setvalue(name,"offset",value)
end
local function synchronize(name,d)
local dc = d.counter
if dc then
if trace_counters then
- report_counters("setting counter %s with name %s to %s",dc,name,d.number)
+ report_counters("synchronize, counter: %s, name: %s, value: %s, action: setting",dc,name,d.number)
end
- tex.setcount("global",dc,d.number)
+ texsetcount("global",dc,d.number)
end
local cs = counterspecials[name]
if cs then
if trace_counters then
- report_counters("invoking special for name %s",name)
+ report_counters("synchronize, counter: %s, name: %s, action: special",dc,name)
end
- cs()
+ cs(name)
end
end
-function counters.reset(name,n)
+local function reset(name,n)
local cd = counterdata[name]
if cd then
for i=n or 1,#cd.data do
local d = cd.data[i]
savevalue(name,i)
- d.number = d.start or 0
+ local number = d.start or 0
+ d.number = number
d.own = nil
+ if trace_counters then
+ report_counters("resetting, name: %s, sub: %s, value: %s",name,i,number)
+ end
synchronize(name,d)
end
cd.numbers = nil
+ else
end
end
-function counters.set(name,n,value)
+local function set(name,n,value)
local cd = counterdata[name]
if cd then
local d = allocate(name,n)
- d.number = value or 0
+ local number = value or 0
+ d.number = number
d.own = nil
+ if trace_counters then
+ report_counters("setting, name: %s, value: %s",name,number)
+ end
synchronize(name,d)
end
end
@@ -313,12 +366,19 @@ local function check(name,data,start,stop)
for i=start or 1,stop or #data do
local d = data[i]
savevalue(name,i)
- d.number = d.start or 0
+ local number = d.start or 0
+ d.number = number
d.own = nil
+ if trace_counters then
+ report_counters("checking, name: %s, sub: %s, value: %s",name,i,number)
+ end
synchronize(name,d)
end
end
+counters.reset = reset
+counters.set = set
+
function counters.setown(name,n,value)
local cd = counterdata[name]
if cd then
@@ -328,7 +388,7 @@ function counters.setown(name,n,value)
local level = cd.level
if not level or level == -1 then
-- -1 is signal that we reset manually
- elseif level > 0 then
+ elseif level > 0 or level == -3 then
check(name,d,n+1)
elseif level == 0 then
-- happens elsewhere, check this for block
@@ -345,7 +405,7 @@ function counters.restart(name,n,newstart,noreset)
local d = allocate(name,n)
d.start = newstart
if not noreset then
- counters.reset(name,n) -- hm
+ reset(name,n) -- hm
end
end
end
@@ -367,24 +427,38 @@ end
function counters.add(name,n,delta)
local cd = counterdata[name]
--- inspect(cd)
- if cd and (cd.state == variables.start or cd.state == "") then
+ if cd and (cd.state == v_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
+ if trace_counters then
+ report_counters("adding, name: %s, level: manually, action: no checking",name)
+ end
elseif level == -2 then
-- -2 is signal that we work per text
+ if trace_counters then
+ report_counters("adding, name: %s, level: text, action: checking",name)
+ end
check(name,data,n+1)
- elseif level > 0 then
+ elseif level > 0 or level == -3 then
-- within countergroup
+ if trace_counters then
+ report_counters("adding, name: %s, level: %s, action: checking within group",name,level)
+ end
check(name,data,n+1)
elseif level == 0 then
-- happens elsewhere
+ if trace_counters then
+ report_counters("adding, name: %s, level: %s, action: no checking",name,level)
+ end
+ else
+ if trace_counters then
+ report_counters("adding, name: %s, level: unknown, action: no checking",name)
+ end
end
synchronize(name,d)
return d.number -- not needed
@@ -392,19 +466,23 @@ function counters.add(name,n,delta)
return 0
end
-function counters.check(level) -- not used (yet)
+function counters.check(level)
for name, cd in next, counterdata do
- -- report_counters("%s %s %s",name,cd.level,level)
- if cd.level == level then
+ if level > 0 and cd.level == -3 then -- could become an option
if trace_counters then
- report_counters("resetting %s at level %s",name,level)
+ report_counters("resetting, name: %s, level: %s (head)",name,level)
end
- counters.reset(name)
+ reset(name)
+ elseif cd.level == level then
+ if trace_counters then
+ report_counters("resetting, name: %s, level: %s (normal)",name,level)
+ end
+ reset(name)
end
end
end
-function counters.get(name,n,key)
+local function get(name,n,key)
local d = allocate(name,n)
d = d and d[key]
if not d then
@@ -416,8 +494,10 @@ function counters.get(name,n,key)
end
end
+counters.get = get
+
function counters.value(name,n) -- what to do with own
- return counters.get(name,n or 1,'number') or 0
+ return get(name,n or 1,'number') or 0
end
function counters.converted(name,spec) -- name can be number and reference to storage
@@ -431,9 +511,8 @@ function counters.converted(name,spec) -- name can be number and reference to st
if cd then
local spec = spec or { }
local numbers, ownnumbers = { }, { }
- local reverse = spec.order == variables.reverse
+ local reverse = spec.order == v_reverse
local kind = spec.type or "number"
- local v_first, v_next, v_previous, v_last = variables.first, variables.next, variables.previous, variables.last
local data = cd.data
for k=1,#data do
local v = data[k]
@@ -446,7 +525,7 @@ function counters.converted(name,spec) -- name can be number and reference to st
vn = v.first
elseif kind == v_next then
vn = v.next
- elseif kind == v_previous then
+ elseif kind == v_prev or kind == v_previous then
vn = v.prev
elseif kind == v_last then
vn = v.last
@@ -498,7 +577,7 @@ function commands.showcounter(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)
+ 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
@@ -543,7 +622,7 @@ end
--~ return cd, false, "no section data"
--~ end
--~ -- local preferences
---~ local no = variables.no
+--~ local no = v_no
--~ if counterspecification and counterspecification.prefix == no then
--~ return cd, false, "current spec blocks prefix"
--~ end
diff --git a/tex/context/base/strc-num.mkiv b/tex/context/base/strc-num.mkiv
index 9c08693be..d8815d423 100644
--- a/tex/context/base/strc-num.mkiv
+++ b/tex/context/base/strc-num.mkiv
@@ -19,6 +19,7 @@
% work in progress
% to be checked: can we use the command handler code here?
+% all settings will move to lua
\installcorenamespace{counter}
@@ -31,7 +32,7 @@
% \c!prefixstopper=,
\c!prefixconnector=.,
\c!prefixsegments=\autostructureprefixsegments\sharedcounterparameter,
- \c!start=0,
+ \c!start=\zerocount,
\c!prefix=\v!yes,
\c!state=\v!start]
@@ -79,9 +80,10 @@
\def\strc_counters_define_yes[#1][#2]%
{\getparameters[\??counter#1][\s!counter=,#2]% counter is for internal purposes
+ \edef\p_start{\counterparameter{#1}\c!start}%
\ctxcommand{definecounter {
name = "#1",
- start = tonumber("\counterparameter{#1}\c!start") or 0,
+ start = \ifx\p_start\empty0\else\number\p_start\fi,
counter = "\counterparameter{#1}\s!counter",
method = "\counterparameter{#1}\c!method",
}}%
@@ -94,8 +96,12 @@
\unexpanded\def\setupcounter
{\dodoubleargument\strc_counters_setup}
+% \def\strc_counters_setup[#1][#2]%
+% {\getparameters[\??counter#1][\c!start=,#2]% hm, start
+% \strc_counters_check_setup{#1}}
+
\def\strc_counters_setup[#1][#2]%
- {\getparameters[\??counter#1][\c!start=,#2]%
+ {\getparameters[\??counter#1][#2]% no start here
\strc_counters_check_setup{#1}}
% % % %
@@ -109,20 +115,6 @@
\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
@@ -133,7 +125,8 @@
% it's a clone
\else
\edef\currentcounterlevel{\thenamedcounterlevel{#1}}%
- \ctxcommand{checkcountersetup("#1",\currentcounterlevel,"\counterparameter{#1}\c!start","\counterparameter{#1}\c!state")}%
+ \edef\p_start{\counterparameter{#1}\c!start}%
+ \ctxcommand{checkcountersetup("#1",\currentcounterlevel,\ifx\p_start\empty0\else\number\p_start\fi,"\counterparameter{#1}\c!state")}%
\fi}
\unexpanded\def\doifcounterelse #1{\ctxcommand{doifelsecounter("\strc_counters_the{#1}")}}
@@ -507,22 +500,20 @@
% \m_strc_counters_last_registered_attribute
% \m_strc_counters_last_registered_synchronize
-\newconditional\hascountercaption
-\newconditional\hascountertitle
-\newconditional\hascounternumber
+% currentstructurecomponent => \strc_current_ or just \m_strc_
\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\hascounterlevel {#3\s!haslevel}%
- \edef\hascountercaption{#3\s!hascaption}%
- \edef\hascountertitle {#3\s!hastitle}%
- \edef\hascounternumber {#3\s!hasnumber}%
+ \edef\p_haslevel {#3\s!haslevel}%
+ \edef\p_hascaption{#3\s!hascaption}%
+ \edef\p_hastitle {#3\s!hastitle}%
+ \edef\p_hasnumber {#3\s!hasnumber}%
%
- \edef\askedprefixsegments{#3\c!prefixsegments}%
- \ifx\askedprefixsegments\v!auto
- \edef\askedprefixsegments{\autostructureprefixsegments#3}%
+ \edef\p_prefixsegments{#3\c!prefixsegments}%
+ \ifx\p_prefixsegments\v!auto
+ \edef\p_prefixsegments{\autostructureprefixsegments#3}%
\fi
%
\edef\currentname{#3\c!name}%
@@ -534,7 +525,7 @@
\let\currentcounter\currentname
\fi
%
- \ifx\hascountercaption\v!yes
+ \ifx\p_hascaption\v!yes
\xdef\currentstructurecomponentname {#3\c!name}%
\xdef\currentstructurecomponentlevel {#3\c!level}%
\edef\currentstructurecomponentexpansion {#3\c!expansion}%
@@ -613,7 +604,7 @@
list = \!!bs\detokenize\expandafter{\currentstructurecomponentlist}\!!es,
\fi
},
- \ifx\hascounternumber\v!yes
+ \ifx\p_hasnumber\v!yes
prefixdata = {
prefix = "#3\c!prefix",
separatorset = "#3\c!prefixseparatorset",
@@ -621,7 +612,7 @@
conversionset = "#3\c!prefixconversionset",
set = "#3\c!prefixset",
% segments = "#3\c!prefixsegments",
- segments = "\askedprefixsegments",
+ segments = "\p_prefixsegments",
connector = \!!bs#3\c!prefixconnector\!!es,
},
numberdata = {
@@ -637,7 +628,7 @@
userdata = \!!bs\detokenize{#9}\!!es % will be converted to table at the lua end
}
}}%
- \xdef\m_strc_counters_last_registered_attribute {\ctxlua {tex.write(structures.references.setinternalreference(nil,nil,\nextinternalreference))}}%
+ \xdef\m_strc_counters_last_registered_attribute {\ctxcommand {setinternalreference(nil,nil,\nextinternalreference)}}%
\xdef\m_strc_counters_last_registered_synchronize{\ctxlatecommand{enhancelist(\m_strc_counters_last_registered_index)}}%
\else
\glet\m_strc_counters_last_registered_index \relax
@@ -651,9 +642,10 @@
\let\m_strc_counters_last_registered_synchronize\relax
\def\strc_counter_setup_using_parameter#1#2% name \someparameter
- {\setupcounter
+ {\edef\p_start{#2\c!start}%
+ \normalexpanded{\setupcounter
[#1]
- [ \c!start=#2\c!start,
+ [ \c!start=\ifx\p_start\empty0\else\number\p_start\fi,
\c!state=#2\c!state, % beware, "" == start
\c!way=#2\c!way,
%
@@ -673,7 +665,7 @@
\c!numberconversionset=#2\c!numberconversionset,
\c!numberstarter=#2\c!numberstarter,
\c!numberstopper=#2\c!numberstopper,
- \c!numbersegments=#2\c!numbersegments]}
+ \c!numbersegments=#2\c!numbersegments]}}
\def\strc_counter_preset_using_parameter#1#2% \setupcommand \someparameter
{#1%
diff --git a/tex/context/base/strc-pag.lua b/tex/context/base/strc-pag.lua
index 460d4ff00..bce965546 100644
--- a/tex/context/base/strc-pag.lua
+++ b/tex/context/base/strc-pag.lua
@@ -69,6 +69,9 @@ function pages.save(prefixdata,numberdata)
end
end
+-- We can set the pagenumber but as it only get incremented in the page
+-- builder we have to make sure it starts at least at 1.
+
function counters.specials.userpage()
local r = texcount.realpageno
if r > 0 then
@@ -78,7 +81,16 @@ function counters.specials.userpage()
if trace_pages then
report_pages("forcing pagenumber of realpage %s to %s",r,t.number)
end
+ return
+ end
+ end
+ local u = texcount.userpageno
+ if u == 0 then
+ if trace_pages then
+ report_pages("forcing pagenumber of realpage %s to %s (probably a bug)",r,1)
end
+ counters.setvalue("userpage",1)
+ texcount.userpageno = 1
end
end
diff --git a/tex/context/base/strc-pag.mkiv b/tex/context/base/strc-pag.mkiv
index e3828464c..8071fbab1 100644
--- a/tex/context/base/strc-pag.mkiv
+++ b/tex/context/base/strc-pag.mkiv
@@ -19,11 +19,11 @@
% Allocation:
-\countdef\realpageno = 0 \realpageno = 1
-\countdef\userpageno = 1 \userpageno = 1
-\countdef\subpageno = 2 \subpageno = 0 % !!
-\countdef\arrangeno = 3 \arrangeno = 0 % !!
-\countdef\pagenoshift = 4 \pagenoshift = 0 % !!
+\countdef\realpageno \zerocount \realpageno \plusone
+\countdef\userpageno \plusone \userpageno \plusone
+\countdef\subpageno \plustwo \subpageno \zerocount % !
+\countdef\arrangeno \plusthree \arrangeno \zerocount % !
+\countdef\pagenoshift\plusfour \pagenoshift\zerocount % !
\let\pageno\userpageno
@@ -33,7 +33,8 @@
\newtoks\everyinitializepagecounters
-\def\initializepagecounters{\the\everyinitializepagecounters}
+\unexpanded\def\initializepagecounters
+ {\the\everyinitializepagecounters}
\appendtoks
\initializepagecounters
@@ -71,27 +72,30 @@
% \stopbodymatter
% \stoptext
-\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]
+\definecounter[\s!realpage][\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=realpageno,\c!method=\v!page]
+\definecounter[\s!userpage][\c!prefix=\v!no,\c!start=\plusone,\c!prefixsegments=,\s!counter=userpageno,\c!method=\v!page]
+\definecounter[\s!subpage] [\c!prefix=\v!no,\c!start=\plusone,\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
\newtoks\everysetupsubpagenumber % todo: set state: none, start, stop, reset
-\unexpanded\def\setuprealpagenumber{\dosingleargument\dosetuprealpagenumber}
-\unexpanded\def\setupuserpagenumber{\dosingleargument\dosetupuserpagenumber}
-\unexpanded\def\setupsubpagenumber {\dosingleargument\dosetupsubpagenumber}
+\unexpanded\def\setuprealpagenumber{\dosingleargument\strc_pagenumbers_setup_realpage}
+\unexpanded\def\setupuserpagenumber{\dosingleargument\strc_pagenumbers_setup_userpage}
+\unexpanded\def\setupsubpagenumber {\dosingleargument\strc_pagenumbers_setup_subpage }
-\def\dosavepagenumberstate#1{\edef\oldpagenumberstate{\counterparameter#1\c!state}}
+\let\m_strc_pagenumbers_state_old\zerocount
+\let\m_strc_pagenumbers_state_new\zerocount
-\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\strc_pagenumbers_save_state#1{\edef\m_strc_pagenumbers_state_old\m_strc_pagenumbers_state_old{\counterparameter#1\c!state}}
-\def\resetrealpagenumber {} % not permitted
-\def\resetuserpagenumber {\strc_counters_reset\s!userpage}
-\def\resetsubpagenumber {\strc_counters_reset\s!subpage}
+\def\strc_pagenumbers_setup_realpage[#1]{\strc_pagenumbers_save_state\s!realpage\strc_counters_setup[\s!realpage][#1]\the\everysetuprealpagenumber}
+\def\strc_pagenumbers_setup_userpage[#1]{\strc_pagenumbers_save_state\s!userpage\strc_counters_setup[\s!userpage][#1]\the\everysetupuserpagenumber}
+\def\strc_pagenumbers_setup_subpage [#1]{\strc_pagenumbers_save_state\s!subpage \strc_counters_setup[\s!subpage ][#1]\the\everysetupsubpagenumber }
+
+\unexpanded\def\resetrealpagenumber {} % not permitted
+\unexpanded\def\resetuserpagenumber {\strc_counters_reset\s!userpage}
+\unexpanded\def\resetsubpagenumber {\strc_counters_reset\s!subpage}
\appendtoks
\strc_counters_set\s!realpage\realpageno
@@ -102,7 +106,7 @@
\let\setuppagenumber\setupuserpagenumber
\let\resetpagenumber\resetuserpagenumber
-\def\savecurrentpagestate % \normalexpanded?
+\def\strc_pagenumbers_page_state_save % \normalexpanded?
{\ctxlua{structures.pages.save({
prefix = "\counterparameter\s!userpage\c!prefix",
separatorset = "\counterparameter\s!userpage\c!prefixseparatorset",
@@ -120,11 +124,13 @@
)}}
\prependtoks
- \savecurrentpagestate
+ \strc_pagenumbers_page_state_save
\to \everyshipout
-\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}]}}
+\installcorenamespace{pagestatestack} % no level yet
+
+\unexpanded\def\strc_pagenumbers_page_state_push{\setxvalue{\??pagestatestack\c!state}{\counterparameter\s!userpage\c!state}}
+\unexpanded\def\strc_pagenumbers_page_state_pop {\normalexpanded{\setuppagenumber[\c!state=\getvalue{\??pagestatestack\c!state}]}}
\setuppagenumber
[\c!way=\v!by\v!text,
@@ -207,17 +213,17 @@
\def\nextuserpagenumber {\directconvertedcounter\s!userpage\v!next}
\def\nextsubpagenumber {\directconvertedcounter\s!subpage \v!next}
-\def\dodeincrementpageboundcounters % only at the end
+\unexpanded\def\strc_pagenumbers_decrement_counters % only at the end
{\strc_counters_decrement\s!realpage
\strc_counters_decrement\s!userpage
\strc_counters_decrement\s!subpage}
-\def\doincrementpageboundcounters
+\unexpanded\def\strc_pagenumbers_increment_counters
{\incrementpagenumber
\incrementsubpagenumber}
\appendtoks
- \dodeincrementpageboundcounters
+ \strc_pagenumbers_decrement_counters
\to \everygoodbye
% Equivalents (compatibility):
@@ -238,61 +244,49 @@
% States:
-\newif\ifrightpage \rightpagetrue
\newif\ifdoublesided \newconditional\layoutisdoublesided
\newif\ifsinglesided \newconditional\layoutissinglesided
% Realpage and subpage numbers:
-\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax}
-\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax}
+\unexpanded\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax}
+\unexpanded\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax}
% Page numbers: (can move to lua) ... inconsistent names
-\def\dodecrementpagenumber {\global\userpageno\strc_counters_decremented\s!userpage\relax}
-\def\doincrementpagenumber {\global\userpageno\strc_counters_incremented\s!userpage\relax}
+\installcorenamespace{pagenumberinc}
+\installcorenamespace{pagenumberdec}
-\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax}
-\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax}
+\unexpanded\def\strc_pagenumbers_decrement_userpage{\global\userpageno\strc_counters_decremented\s!userpage\relax}
+\unexpanded\def\strc_pagenumbers_increment_userpage{\global\userpageno\strc_counters_incremented\s!userpage\relax}
-\def\dosynchronizepagenumber{\global\let\@@pnstate\v!start}
+\unexpanded\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax}
+\unexpanded\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax}
-\def\decrementpagenumber{\csname\??pn-\counterparameter\s!userpage\c!state\endcsname}
-\def\incrementpagenumber{\csname\??pn+\counterparameter\s!userpage\c!state\endcsname}
+\unexpanded\def\strc_pagenumbers_synchronize_userpage{\global\c_strc_pagenumbers_state_userpage\plustwo} % start and visible
-\letvalue{\??pn-\v!start}\dodecrementpagenumber
-\letvalue{\??pn-\v!none }\dodecrementpagenumber
-\letvalue{\??pn-\v!empty}\dodecrementpagenumber
+\unexpanded\def\decrementpagenumber{\csname\??pagenumberdec\counterparameter\s!userpage\c!state\endcsname}
+\unexpanded\def\incrementpagenumber{\csname\??pagenumberinc\counterparameter\s!userpage\c!state\endcsname}
-\letvalue{\??pn+\v!start}\doincrementpagenumber
-\letvalue{\??pn+\v!none }\doincrementpagenumber
-\setvalue{\??pn+\v!empty}{\doincrementpagenumber\dosynchronizepagenumber}
-\letvalue{\??pn+\v!keep }\dosynchronizepagenumber
+\letvalue{\??pagenumberdec\v!start}\strc_pagenumbers_decrement_userpage
+\letvalue{\??pagenumberdec\v!none }\strc_pagenumbers_decrement_userpage
+\letvalue{\??pagenumberdec\v!empty}\strc_pagenumbers_decrement_userpage
-% Control:
-
-\def\getpagestatus % hierboven gebruiken
- {\ifdoublesided
- \global\rightpagetrue
- % todo: \global\rightpagetrue or \global\rightpagefalse
- \else
- \global\rightpagetrue
- \fi}
+\letvalue{\??pagenumberinc\v!start}\strc_pagenumbers_increment_userpage
+\letvalue{\??pagenumberinc\v!none }\strc_pagenumbers_increment_userpage
+\setvalue{\??pagenumberinc\v!empty}{\strc_pagenumbers_increment_userpage\strc_pagenumbers_synchronize_userpage}
+\letvalue{\??pagenumberinc\v!keep }\strc_pagenumbers_synchronize_userpage
% Setup general page numbering
-\newtoks\everysetuppagenumbering
+\installcorenamespace{pagenumbering}
-\unexpanded\def\setuppagenumbering
- {\dosingleempty\dosetuppagenumbering}
-
-\def\dosetuppagenumbering[#1]%
- {\getparameters[\??nm][#1]\the\everysetuppagenumbering}
+\installdirectcommandhandler \??pagenumbering {pagenumbering}
\appendtoks
\singlesidedfalse \setfalse\layoutisdoublesided
\doublesidedfalse \setfalse\layoutissinglesided
- \normalexpanded{\noexpand\processallactionsinset[\@@nmalternative]}
+ \processallactionsinset[\directpagenumberingparameter\c!alternative]
[ \v!singlesided=>\singlesidedtrue\settrue\layoutissinglesided,
\v!doublesided=>\doublesidedtrue\settrue\layoutisdoublesided]%
\ifdefined\trackingmarginnotestrue
@@ -303,19 +297,24 @@
\fi
\fi
\page_backgrounds_recalculate
- \dosetpagenumberlocation
+ \strc_pagenumbers_set_location
\to \everysetuppagenumbering
\ifdefined \page_backgrounds_recalculate \else
\let\page_backgrounds_recalculate\relax
\fi
-\ifdefined \dosetpagenumberlocation \else
- \let\dosetpagenumberlocation\relax
+\ifdefined \strc_pagenumbers_set_location \else
+ \let\strc_pagenumbers_set_location\relax
\fi
-\def\flushfinallayoutpage
- {\doifsomething\@@nmpage{\doifnot\@@nmpage\v!no{\page[\@@nmpage]}}}
+\unexpanded\def\strc_pagenumbers_flush_final_page
+ {\edef\p_strc_pagenumbers_page{\directpagenumberingparameter\c!page}%
+ \ifx\p_strc_pagenumbers_page\empty \else
+ \ifx\p_strc_pagenumbers_page\v!no \else
+ \page[\p_strc_pagenumbers_page]
+ \fi
+ \fi}
% The numbered location handler is there because we need to be downward
% compatible. So, in fact there can be multiple handlers active at the
@@ -323,28 +322,32 @@
% Rendering:
-\unexpanded\def\placelocationpagenumber
- {\ifnum\userpagenumberstate=\plustwo
- \ifnum\overallpagenumberstate=\plusone
- \doif\@@nmstrut\v!yes\strut
+\unexpanded\def\strc_pagenumbers_place_location
+ {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
+ \ifnum\c_strc_pagenumbers_state=\plusone
+ \doif{\directpagenumberingparameter\c!strut}\v!yes\strut
\begingroup
- \dousestyleparameter\@@nmstyle
- \dousecolorparameter\@@nmcolor
- \@@nmcommand{\@@nmleft\labeltexts\v!pagenumber{\prefixedpagenumber}\@@nmright}%
+ \usepagenumberingstyleandcolor\c!style\c!color
+ \directpagenumberingparameter\c!command
+ {\directpagenumberingparameter\c!left
+ \labeltexts\v!pagenumber\prefixedpagenumber
+ \directpagenumberingparameter\c!right}%
\endgroup
\fi
\fi}
\unexpanded\def\completepagenumber
- {\ifnum\userpagenumberstate=\plustwo
- \ifnum\overallpagenumberstate=\plusone
- \@@nmleft\labeltexts\v!pagenumber\prefixedpagenumber\@@nmright
+ {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
+ \ifnum\c_strc_pagenumbers_state=\plusone
+ \directpagenumberingparameter\c!left
+ \labeltexts\v!pagenumber\prefixedpagenumber
+ \directpagenumberingparameter\c!right
\fi
\fi}
\unexpanded\def\placepagenumber
- {\ifnum\userpagenumberstate=\plustwo
- \ifnum\overallpagenumberstate=\plusone
+ {\ifnum\c_strc_pagenumbers_state_userpage=\plustwo
+ \ifnum\c_strc_pagenumbers_state=\plusone
\labeltexts\v!pagenumber\pagenumber
\fi
\fi}
@@ -356,35 +359,35 @@
% compatible. So, in fact there can be multiple handlers active at the
% same time, but only the current one does something.
-\setnewconstant\realpagenumberstate \plustwo % counter state : 0=stop, 1=start, 2=start and visible
-\setnewconstant\userpagenumberstate \plustwo % counter state : 0=stop, 1=start, 2=start and visible
-\setnewconstant\subpagenumberstate \plustwo % counter state : 0=stop, 1=start, 2=start and visible
-\setnewconstant\overallpagenumberstate\plusone % general number: 0=invisible, 1=visible
+\setnewconstant\c_strc_pagenumbers_state_realpage\plustwo % counter state : 0=stop, 1=start, 2=start and visible
+\setnewconstant\c_strc_pagenumbers_state_userpage\plustwo % counter state : 0=stop, 1=start, 2=start and visible
+\setnewconstant\c_strc_pagenumbers_state_subpage \plustwo % counter state : 0=stop, 1=start, 2=start and visible
+\setnewconstant\c_strc_pagenumbers_state \plusone % general number: 0=invisible, 1=visible
-\def\checkpagenumberstatechange#1#2%
- {\edef\newpagenumberstate{\counterparameter#1\c!state}%
- \ifx\newpagenumberstate\oldpagenumberstate \else
- \doifelse\newpagenumberstate\v!start
+\unexpanded\def\strc_pagenumbers_check_state_change#1#2%
+ {\edef\m_strc_pagenumbers_state_new{\counterparameter#1\c!state}%
+ \ifx\m_strc_pagenumbers_state_new\m_strc_pagenumbers_state_old \else
+ \doifelse\m_strc_pagenumbers_state_new\v!start
{#2\plustwo}%
{#2\zerocount}%
\fi}
\appendtoks % todo: set state: none, start, stop, reset
- \checkpagenumberstatechange\s!realpage\realpagenumberstate
+ \strc_pagenumbers_check_state_change\s!realpage\c_strc_pagenumbers_state_realpage
\to \everysetuprealpagenumber
\appendtoks % todo: set state: none, start, stop, reset
- \checkpagenumberstatechange\s!userpage\userpagenumberstate
+ \strc_pagenumbers_check_state_change\s!userpage\c_strc_pagenumbers_state_userpage
\to \everysetupuserpagenumber
\appendtoks % todo: set state: none, start, stop, reset
- \checkpagenumberstatechange\s!subpage\subpagenumberstate
+ \strc_pagenumbers_check_state_change\s!subpage\c_strc_pagenumbers_state_subpage
\to \everysetupsubpagenumber
\appendtoks % todo: set state: none, start, stop, reset
- \doifelse\@@nmstate\v!start
- {\overallpagenumberstate\plusone }%
- {\overallpagenumberstate\zerocount}%
+ \doifelse{\directpagenumberingparameter\c!state}\v!start
+ {\c_strc_pagenumbers_state\plusone }%
+ {\c_strc_pagenumbers_state\zerocount}%
\to \everysetuppagenumbering
% Done
@@ -415,7 +418,7 @@
\appendtoks
\edef\askeduserpagenumber{\counterparameter\s!userpage\c!number}%
\ifx\askeduserpagenumber\empty \else
- \normalexpanded{\setuppagenumber[\c!start=\counterparameter\s!userpage\c!number,\c!number=]}%
+ \normalexpanded{\setuppagenumber[\c!start=\askeduserpagenumber,\c!number=]}%
\userpageno\strc_counters_raw\s!userpage
\fi
\to \everysetupuserpagenumber % todo: set state: none, start, stop, reset
@@ -423,7 +426,7 @@
\appendtoks
\edef\askedsubpagenumber{\counterparameter\s!subpage\c!number}%
\ifx\askedsubpagenumber\empty \else
- \normalexpanded{\setupsubpagenumber[\c!start=\counterparameter\s!subpage\c!number,\c!number=]}%
+ \normalexpanded{\setupsubpagenumber[\c!start=\askedsubpagenumber,\c!number=]}%
\subpageno\strc_counters_raw\s!subpage\relax
\fi
\to \everysetupsubpagenumber % todo: set state: none, start, stop, reset
@@ -433,7 +436,7 @@
% \setupuserpagenumber[start=2]
% \starttext \dorecurse{20}{\input knuth \par} \stoptext
-\def\checkpagenumbershift
+\unexpanded\def\strc_pagenumbers_check_change_shift
{\userpageno\strc_counters_raw\s!userpage\relax
\ifnum\realpageno=\plusone
\ifodd\userpageno
@@ -444,12 +447,12 @@
\appendtoks % todo: set state: none, start, stop, reset
% this makes starting at an even page possible
- \checkpagenumbershift
+ \strc_pagenumbers_check_change_shift
\to \everysetupuserpagenumber
\appendtoks % todo: set state: none, start, stop, reset
% this makes starting at an even page possible
- \checkpagenumbershift
+ \strc_pagenumbers_check_change_shift
\to \everysetuppagenumbering
\initializepagecounters
diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua
index 092babfae..ab2d366cc 100644
--- a/tex/context/base/strc-ref.lua
+++ b/tex/context/base/strc-ref.lua
@@ -29,6 +29,12 @@ local trace_analyzing = false trackers.register("structures.referencing.anal
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 check_duplicates = true
+
+directives.register("structures.referencing.checkduplicates", function(v)
+ check_duplicates = v
+end)
+
local report_references = logs.reporter("references")
local report_unknown = logs.reporter("unknown")
local report_identifying = logs.reporter("references","identifying")
@@ -38,6 +44,12 @@ local variables = interfaces.variables
local constants = interfaces.constants
local context = context
+local v_default = variables.default
+local v_url = variables.url
+local v_file = variables.file
+local v_unknown = variables.unknown
+local v_yes = variables.yes
+
local texcount = tex.count
local texconditionals = tex.conditionals
@@ -237,11 +249,13 @@ references.setnextorder = setnextorder
function references.setnextinternal(kind,name)
setnextorder(kind,name) -- always incremented with internal
- texsetcount("global","locationcount",texcount.locationcount + 1)
+ local n = texcount.locationcount + 1
+ texsetcount("global","locationcount",n)
+ return n
end
function references.currentorder(kind,name)
- context(orders[kind] and orders[kind][name] or lastorder)
+ return orders[kind] and orders[kind][name] or lastorder
end
local function setcomponent(data)
@@ -257,6 +271,12 @@ local function setcomponent(data)
-- but for the moment we do it here (experiment)
end
+commands.setnextinternalreference = references.setnextinternal
+
+function commands.currentreferenceorder(kind,name)
+ context(references.currentorder(kind,name))
+end
+
references.setcomponent = setcomponent
function references.set(kind,prefix,tag,data)
@@ -269,7 +289,7 @@ function references.set(kind,prefix,tag,data)
local n = 0
for ref in gmatch(tag,"[^,]+") do
if ref ~= "" then
- if pd[ref] then
+ if check_duplicates and pd[ref] then
if prefix and prefix ~= "" then
report_references("redundant reference: %q in namespace %q",ref,prefix)
else
@@ -292,6 +312,8 @@ function references.enhance(prefix,tag)
end
end
+commands.enhancereference = references.enhance
+
-- -- -- related to strc-ini.lua -- -- --
references.resolvers = references.resolvers or { }
@@ -400,7 +422,9 @@ function references.urls.define(name,url,file,description)
end
end
-local pushcatcodes, popcatcodes, txtcatcodes = context.pushcatcodes, context.popcatcodes, tex.txtcatcodes
+local pushcatcodes = context.pushcatcodes
+local popcatcodes = context.popcatcodes
+local txtcatcodes = catcodes.numbers.txtcatcodes -- or just use "txtcatcodes"
function references.urls.get(name)
local u = urls[name]
@@ -526,9 +550,7 @@ end
function references.programs.get(name)
local f = programs[name]
- if f then
- context(f[1])
- end
+ return f and f[1]
end
function references.checkedprogram(whatever) -- return whatever if not resolved
@@ -542,10 +564,19 @@ function references.checkedprogram(whatever) -- return whatever if not resolved
end
end
+commands.defineprogram = references.programs.define
+
+function commands.getprogram(name)
+ local f = programs[name]
+ if f then
+ context(f[1])
+ end
+end
+
-- shared by urls and files
function references.whatfrom(name)
- context((urls[name] and variables.url) or (files[name] and variables.file) or variables.unknown)
+ context((urls[name] and v_url) or (files[name] and v_file) or v_unknown)
end
function references.from(name)
@@ -553,6 +584,31 @@ function references.from(name)
if u then
local url, file, description = u[1], u[2], u[3]
if description ~= "" then
+ return description
+ -- ok
+ elseif file and file ~= "" then
+ return url .. "/" .. file
+ else
+ return url
+ end
+ else
+ local f = files[name]
+ if f then
+ local file, description = f[1], f[2]
+ if description ~= "" then
+ return description
+ else
+ return file
+ end
+ end
+ end
+end
+
+function commands.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
@@ -578,10 +634,6 @@ function references.define(prefix,reference,list)
d[reference] = { "defined", list }
end
---~ function references.registerspecial(name,action,...)
---~ specials[name] = { action, ... }
---~ end
-
function references.reset(prefix,reference)
local d = defined[prefix]
if d then
@@ -589,6 +641,9 @@ function references.reset(prefix,reference)
end
end
+commands.definereference = references.define
+commands.resetreference = references.reset
+
-- \primaryreferencefoundaction
-- \secondaryreferencefoundaction
-- \referenceunknownaction
@@ -699,6 +754,8 @@ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex
end
end
+commands.expandcurrentreference = references.expandcurrent -- for the moment the same
+
local externals = { }
-- we have prefixes but also components:
@@ -1514,7 +1571,7 @@ references.identify = identify
local unknowns, nofunknowns = { }, 0
-function references.doifelse(prefix,reference,highlight,newwindow,layer)
+function references.valid(prefix,reference,highlight,newwindow,layer)
local set, bug = identify(prefix,reference)
local unknown = bug or #set == 0
if unknown then
@@ -1533,7 +1590,11 @@ function references.doifelse(prefix,reference,highlight,newwindow,layer)
currentreference = set[1]
end
-- we can do the expansion here which saves a call
- commands.doifelse(not unknown)
+ return not unknown
+end
+
+function commands.doifelsereference(prefix,reference,highlight,newwindow,layer)
+ commands.doifelse(references.valid(prefix,reference,highlight,newwindow,layer))
end
function references.reportproblems() -- might become local
@@ -1563,7 +1624,7 @@ function references.setinnermethod(m)
if m then
if m == "page" or m == "mixed" or m == "names" then
innermethod = m
- elseif m == true or m == variables.yes then
+ elseif m == true or m == v_yes then
innermethod = "page"
end
end
@@ -1612,13 +1673,13 @@ function references.setinternalreference(prefix,tag,internal,view) -- needs chec
end
function references.setandgetattribute(kind,prefix,tag,data,view) -- maybe do internal automatically here
- if references.set(kind,prefix,tag,data) then
- texcount.lastdestinationattribute = references.setinternalreference(prefix,tag,nil,view) or unsetvalue
- else
- texcount.lastdestinationattribute = unsetvalue
- end
+ local attr = references.set(kind,prefix,tag,data) and references.setinternalreference(prefix,tag,nil,view) or unsetvalue
+ texcount.lastdestinationattribute = attr
+ return attr
end
+commands.setreferenceattribute = references.setandgetattribute
+
function references.getinternalreference(n) -- n points into list (todo: registers)
local l = lists.collected[n]
return l and l.references.internal or n
@@ -1637,7 +1698,11 @@ end
function references.getcurrentmetadata(tag)
local data = currentreference and currentreference.i
- data = data and data.metadata and data.metadata[tag]
+ return data and data.metadata and data.metadata[tag]
+end
+
+function commands.getcurrentreferencemetadata(tag)
+ local data = references.getcurrentmetadata(tag)
if data then
context(data)
end
@@ -1650,8 +1715,15 @@ end
references.currentmetadata = currentmetadata
-function references.getcurrentprefixspec(default) -- todo: message
- context.getreferencestructureprefix(currentmetadata("kind") or "?",currentmetadata("name") or "?",default or "?")
+local function getcurrentprefixspec(default)
+ -- todo: message
+ return currentmetadata("kind") or "?", currentmetadata("name") or "?", default or "?"
+end
+
+references.getcurrentprefixspec = getcurrentprefixspec
+
+function commands.getcurrentprefixspec(default)
+ context.getreferencestructureprefix(getcurrentprefixspec(default))
end
function references.filter(name,...) -- number page title ...
@@ -1682,6 +1754,10 @@ function references.filter(name,...) -- number page title ...
end
end
+function references.filterdefault()
+ return references.filter("default",getcurrentprefixspec(v_default))
+end
+
filters.generic = { }
function filters.generic.title(data)
@@ -2049,10 +2125,13 @@ end
-- needs a better split ^^^
-commands.filterreference = references.filter
+commands.filterreference = references.filter
+commands.filterdefaultreference = references.filterdefault
-- done differently now:
function references.export(usedname) end
function references.import(usedname) end
function references.load (usedname) end
+
+commands.exportreferences = references.export
diff --git a/tex/context/base/strc-ref.mkvi b/tex/context/base/strc-ref.mkvi
index ee45d76fa..7efc967b7 100644
--- a/tex/context/base/strc-ref.mkvi
+++ b/tex/context/base/strc-ref.mkvi
@@ -61,20 +61,42 @@
% \definespecial\dosetexecuteJScode
% ...
-%D This module deals with referencing. In \CONTEXT\ referencing
-%D is one of the core features, although at a first glance
-%D probably nobody will notice. This is good, because
-%D referencing should be as hidden as possible.
+%D This module deals with referencing. In \CONTEXT\ referencing is one of
+%D the core features, although at a first glance probably nobody will
+%D notice. This is good, because referencing should be as hidden as possible.
%D
-%D In paper documents, referencing comes down to cross
-%D referencing, but in their interactive counterparts, is also
-%D involves navigation. Many features implemented here are
-%D therefore closely related to navigation.
+%D Before we start implementing functionality we provide a way to set
+%D up this mechanism.
%D
-%D Many \CONTEXT\ commands can optionally be fed with a
-%D reference. Such a reference, when called upon, returns the
-%D number of a figure, table, chapter etc, a piece of text, or
-%D a pagenumber.
+%D \showsetup{setupreferencing}
+%D
+%D In interactive documents verbose references don't always
+%D make sense (what is a page number in an unnumbered
+%D document). By setting the \type{interaction} variable, one
+%D can influences the way interactive references are set.
+
+\installcorenamespace{referencing}
+
+\installdirectcommandhandler \??referencing {referencing} % \??referencing
+
+\newif\ifreferencing \referencingtrue
+
+\appendtoks
+ \edef\p_state{\referencingparameter\c!state}%
+ \ifx\p_state\v!start
+ \referencingtrue
+ \else
+ \referencingfalse
+ \fi
+\to \everysetupreferencing
+
+%D In paper documents, referencing comes down to cross referencing, but in
+%D their interactive counterparts, is also involves navigation. Many features
+%D implemented here are therefore closely related to navigation.
+%D
+%D Many \CONTEXT\ commands can optionally be fed with a reference. Such a
+%D reference, when called upon, returns the number of a figure, table, chapter
+%D etc, a piece of text, or a pagenumber.
%D
%D There are three ways of defining a reference:
%D
@@ -96,10 +118,10 @@
%D These are implemented in a low level form as:
-\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}{}}
+\unexpanded\def\strc_references_text_reference [#labels]{\strc_references_set_named_reference\s!text{#labels}{}}
+\unexpanded\def\strc_references_page_reference [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}}
+\unexpanded\def\strc_references_full_reference [#labels]{\strc_references_set_named_reference\s!full{#labels}{}}
+\unexpanded\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
@@ -108,15 +130,15 @@
\newcount\lastreferenceattribute
\newcount\lastdestinationattribute
-\def\dofinishfullreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label")}}}
-\def\dofinishtextreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label",{})}}}
+\def\dofinishfullreference#prefix#label{\normalexpanded{\ctxlatecommand{enhancereference("#prefix","#label")}}}
+\def\dofinishtextreference#prefix#label{\normalexpanded{\ctxlatecommand{enhancereference("#prefix","#label",{})}}}
\let\dofinishpagereference\dofinishfullreference
\let\dofinishuserreference\dofinishfullreference
\def\dofinishsomereference#kind{\executeifdefined{dofinish#{kind}reference}\gobbletwoarguments}
-\def\strc_references_set_named_reference
+\unexpanded\def\strc_references_set_named_reference
{\ifreferencing
\expandafter\strc_references_set_named_reference_indeed
\else
@@ -143,7 +165,7 @@
\edef\currentreferencekind {#kind}%
\edef\currentreferencelabels {#labels}%
\edef\currentreferenceuserdata {#userdata}%
- \edef\currentreferenceexpansion{\@@rfexpansion}% {\referenceparameter\c!expansion}
+ \edef\currentreferenceexpansion{\referencingparameter\c!expansion}% {\referenceparameter\c!expansion}
\ifx\currentreferencelabels\empty
\lastdestinationattribute\attributeunsetvalue
\else
@@ -163,7 +185,7 @@
% beware, the structures.references.set writes a
% \setnextinternalreference
\strc_references_start_destination_nodes
- \ctxlua{structures.references.setandgetattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels",
+ \ctxcommand{setreferenceattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels",
{
references = {
% internal = \nextinternalreference, % no need for an internal as we have an explicit
@@ -210,7 +232,7 @@
\lastdestinationattribute\attributeunsetvalue
\else
\strc_references_start_destination_nodes
- \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","\currentreferencelabels",
+ \ctxcommand{setreferenceattribute("\s!page", "\referenceprefix","\currentreferencelabels",
{
references = {
block = "\currentsectionblock",
@@ -248,7 +270,7 @@
\def\strc_references_set_simple_page_reference#label%
{\iflocation
\strc_references_start_destination_nodes
- \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#label",
+ \ctxcommand{setreferenceattribute("\s!page", "\referenceprefix","#label",
{
references = {
% block = "\currentsectionblock",
@@ -268,13 +290,74 @@
\def\strc_references_get_simple_page_reference#label%
{\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
+ \ctxcommand{injectreference("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
\xdef\currentreferenceattribute{\number\lastreferenceattribute}%
\else
\xdef\currentreferenceattribute{\number\attributeunsetvalue}%
\fi}
%D \macros
+%D {contentreference}
+%D
+%D \starttyping
+%D \setupinteraction
+%D [state=start,
+%D focus=standard]
+%D
+%D \setupheader
+%D [state=stop]
+%D
+%D See page \goto{page 2}[page2] \page
+%D
+%D \contentreference
+%D [page2]
+%D [offset=1cm,toffset=2cm,frame=on]
+%D {\externalfigure[cow.pdf][factor=fit]}
+%D
+%D \stoptyping
+
+\unexpanded\def\contentreference
+ {\hbox\bgroup
+ \dodoubleempty\strc_references_content_pickup}
+
+\def\strc_references_content_pickup
+ {\ifsecondargument
+ \expandafter\strc_references_content_pickup_yes
+ \else
+ \expandafter\strc_references_content_pickup_yes
+ \fi}
+
+\def\strc_references_content_pickup_yes[#1][#2]%
+ {\dowithnextbox{\strc_references_content_yes_finish{#1}{#2}}\hbox}
+
+\def\strc_references_content_pickup_nop[#1][#2]%
+ {\dowithnextbox{\strc_references_content_nop_finish{#1}{#2}}\hbox}
+
+\def\strc_references_content_yes_finish#1#2%
+ {\scratchwidth \wd\nextbox
+ \scratchheight\ht\nextbox
+ \scratchdepth \dp\nextbox
+ \setbox\nextbox\hbox
+ {\framed[\c!frame=\v!off,#2]{\box\nextbox}}%
+ \strc_references_set_simple_page_reference{#1}%
+ \setbox\nextbox\hbox attr \destinationattribute \currentdestinationattribute
+ {\strc_references_flush_destination_nodes
+ \box\nextbox}%
+ \setbox\nextbox\hbox{\box\nextbox}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\scratchdepth
+ \box\nextbox
+ \egroup}
+
+\def\strc_references_content_nop_finish#1#2%
+ {\strc_references_set_simple_page_reference{#1}%
+ \hbox attr \destinationattribute \currentdestinationattribute
+ {\strc_references_flush_destination_nodes
+ \box\nextbox}%
+ \egroup}
+
+%D \macros
%D {everyreference}
%D
%D For rather tricky purposes, one can assign sanitizing
@@ -437,13 +520,13 @@
{\dodoubleempty\strc_references_define_reference}
\def\strc_references_define_reference[#name][#specification]%
- {\ctxlua{structures.references.define("\referenceprefix","#name",\!!bs\detokenize{#specification}\!!es)}}
+ {\ctxcommand{definereference("\referenceprefix","#name",\!!bs\detokenize{#specification}\!!es)}}
\unexpanded\def\resetreference[#name]%
- {\ctxlua{structures.references.reset("\referenceprefix","#name")}}
+ {\ctxcommand{resetreference("\referenceprefix","#name")}}
\def\setpagereference#name#specification% hm,. low level ?
- {\ctxlua{structures.references.define("","#name",\!!bs\v!page(\luaescapestring{#specification})\!!es)}}
+ {\ctxcommand{definereference("","#name",\!!bs\v!page(\luaescapestring{#specification})\!!es)}}
%D Chained references are defined as:
%D
@@ -473,13 +556,13 @@
\newconditional\gotonewwindow \setfalse\gotonewwindow
\def\expandtexincurrentreference % will happen in lua some time
- {\ifcase\referencehastexstate\else\ctxlua{structures.references.expandcurrent()}\fi}
+ {\ifcase\referencehastexstate\else\ctxcommand{expandcurrentreference()}\fi}
\def\expandreferenceoperation#tag#content{\ctxcommand{setreferenceoperation(#tag,\!!bs#content\!!es)}}
\def\expandreferencearguments#tag#content{\ctxcommand{setreferencearguments(#tag,\!!bs#content\!!es)}}
\def\doifreferencefoundelse#labels#yes#nop%
- {\ctxlua{structures.references.doifelse("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}%
+ {\ctxcommand{doifelsereference("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}%
{\expandtexincurrentreference
#yes}%
{#nop}}
@@ -562,8 +645,8 @@
%D the special driver modules (see \type{spec-ini}). The flag
%D \type{\iflocation} signals if we're in interactive mode.
-\ifx\buttonheight\undefined \newdimen\buttonheight \fi
-\ifx\buttonwidth \undefined \newdimen\buttonwidth \fi
+\ifdefined\buttonheight \else \newdimen\buttonheight \fi
+\ifdefined\buttonwidth \else \newdimen\buttonwidth \fi
%D Internal references can best be set using the next few
%D macros. Setting such references to unique values is
@@ -588,14 +671,14 @@
{\global\advance\locationcount\plusone}
\def\setnextinternalreferences#kind#name% plural
- {\ctxlua{structures.references.setnextinternal("#kind","#name")}}
+ {\ctxcommand{setnextinternalreference("#kind","#name")}}
\def\getinternalorderreference#kind#name%
- {\ctxlua{structures.references.currentorder("#kind","#name")}}
+ {\ctxcommand{currentreferenceorder("#kind","#name")}}
\def\thisissomeinternal#kind#name% only for old time sake
{\begingroup
- \ctxlua{structures.references.setinternalreference("","#kind:#name")}%
+ \ctxcommand{setinternalreference("","#kind:#name")}%
\hbox attr \destinationattribute\lastdestinationattribute{}%
\endgroup}
@@ -630,8 +713,6 @@
%D \goto{some text}[\v!action(PreviousJump]
%D \stoptyping
-\newif\ifreferencing \referencingtrue
-
%D One can also activate an automatic prefix mechanism. By
%D setting the \type{\prefix} variable to \type{+}, the prefix
%D is incremented, when set to \type{-} or empty, the prefix is
@@ -639,64 +720,24 @@
\newcount\prefixcounter
-%D These settings are accomplished by:
-%D
-%D \showsetup{setupreferencing}
-%D
-%D In interactive documents verbose references don't always
-%D make sense (what is a page number in an unnumbered
-%D document). By setting the \type{interaction} variable, one
-%D can influences the way interactive references are set.
-
-\newtoks \everysetupreferencing
-
-\unexpanded\def\setupreferencing
- {\dosingleargument\strc_references_setup_referencing}
-
-\def\strc_references_setup_referencing[#settings]%
- {\getparameters[\??rf][\c!prefix=\s!unknown,#settings]%
- \the\everysetupreferencing}
-
-\appendtoks
- \processaction
- [\@@rfstate]
- [ \v!stop=>\referencingfalse,
- \v!start=>\referencingtrue]%
-\to \everysetupreferencing
-
\newconditional\autocrossfilereferences
\appendtoks
- \doifelse\@@rfautofile\v!yes\settrue\setfalse\autocrossfilereferences
+ \edef\p_autofile{\referencingparameter\c!autofile}%
+ \ifx\p_autofile\v!yes
+ \settrue \autocrossfilereferences
+ \else
+ \setfalse\autocrossfilereferences
+ \fi
\to \everysetupreferencing
-\def\exportreferences
- {\doif\@@rfexport\v!yes{\ctxlua{structures.references.export()}}}
-
\appendtoks
- \exportreferences
+ \edef\p_export{\referencingparameter\c!export}%
+ \ifx\p_export\v!yes
+ \ctxcommand{exportreferences()}%
+ \fi
\to \everygoodbye
-\def\incrementreferenceprefix{+}
-\def\decrementreferenceprefix{-}
-
-\unexpanded\def\setupreferenceprefix[#prefix]%
- {\edef\@@rfprefix{#prefix}%
- \ifx\@@rfprefix\empty
- \let\referenceprefix\empty
- \else\ifx\@@rfprefix\incrementreferenceprefix
- \global\advance\prefixcounter \plusone
- \edef\referenceprefix{\the\prefixcounter}%
- \let\@@rfprefix\s!unknown
- \else\ifx\@@rfprefix\decrementreferenceprefix
- \let\referenceprefix\empty
- \let\@@rfprefix\s!unknown
- \else\ifx\@@rfprefix\s!unknown
- % forget about it
- \else
- \edef\referenceprefix{\@@rfprefix}% expanded !
- \fi\fi\fi\fi}
-
\unexpanded\def\setupglobalreferenceprefix[#prefix]%
{\xdef\referenceprefix{#prefix}}
@@ -707,8 +748,28 @@
\unexpanded\def\popreferenceprefix
{\popmacro\referenceprefix}
+\def\m_strc_references_prefix_yes{+}
+\def\m_strc_references_prefix_nop{-}
+
+\unexpanded\def\setupreferenceprefix[#prefix]%
+ {\edef\p_prefix{#prefix}%
+ \ifx\p_prefix\empty
+ \let\referenceprefix\empty
+ \else\ifx\p_prefix\m_strc_references_prefix_yes
+ \letreferencingparameter\c!prefix\s!unknown
+ \global\advance\prefixcounter\plusone
+ \edef\referenceprefix{\the\prefixcounter}%
+ \else\ifx\p_prefix\m_strc_references_prefix_nop
+ \letreferencingparameter\c!prefix\s!unknown
+ \let\referenceprefix\empty
+ \else\ifx\p_prefix\s!unknown
+ % forget about it
+ \else
+ \let\referenceprefix\p_prefix
+ \fi\fi\fi\fi}
+
\appendtoks
- \setupreferenceprefix[\@@rfprefix]
+ \setupreferenceprefix[\referencingparameter\c!prefix]
\to \everysetupreferencing
%D We can typeset a reference using \type{\in}, \type{\at} and
@@ -808,11 +869,11 @@
\let\crlf\space
\let\\\space
\postponenotes
- \@@rfleft
+ \referencingparameter\c!left
\doifreferencefoundelse{#label}
- {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#label]}% not so efficient (dup lookup)
+ {\goto{\limitatetext\currentreferencetitle{\referencingparameter\c!width}\unknown}[#label]}% not so efficient (dup lookup)
{}% todo
- \@@rfright
+ \referencingparameter\c!right
\endgroup}
%D The previously discussed setup macro lets us specify the
@@ -883,7 +944,9 @@
\let\leftofreference \empty
\let\rightofreference \empty
-\setvalue{\??rf\c!interaction\v!all}%
+\installcorenamespace{referencinginteraction}
+
+\setvalue{\??referencinginteraction\v!all}%
{\the\leftreferencetoks
\doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing
\leftofreference
@@ -892,24 +955,24 @@
\doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing
\the\rightreferencetoks}
-\setvalue{\??rf\c!interaction\v!label}%
+\setvalue{\??referencinginteraction\v!label}%
{\leftofreference
\the\leftreferencetoks
\the\rightreferencetoks
\rightofreference}
-\setvalue{\??rf\c!interaction\v!text}%
+\setvalue{\??referencinginteraction\v!text}%
{\leftofreference
\currentreferencecontent
\rightofreference}
-\setvalue{\??rf\c!interaction\v!symbol}%
+\setvalue{\??referencinginteraction\v!symbol}%
{\referencesymbol}
\def\referencesequence
- {\csname \??rf\c!interaction
- \ifcsname\??rf\c!interaction\@@rfinteraction\endcsname
- \@@rfinteraction
+ {\csname\??referencinginteraction
+ \ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
+ \referencingparameter\c!interaction
\else
\v!all
\fi
@@ -1067,7 +1130,7 @@
\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key
\unexpanded\def\autoreferencelabeltext
- {\ctxlua{structures.references.getcurrentmetadata("name")}}
+ {\ctxcommand{getcurrentreferencemetadata("name")}}
% \starttext
% \definereferenceformat[inxx] [left=(,right=),text=txt]
@@ -1144,7 +1207,7 @@
\attribute\referenceattribute\attributeunsetvalue
\global\lastsavedreferenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
+ \ctxcommand{injectreference("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
\setlocationattributes
\setstrut % can be option
\global\lastsavedreferenceattribute\lastreferenceattribute
@@ -1163,7 +1226,7 @@
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#label",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}%
+ \ctxcommand{injectreference("\referenceprefix","#label",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}%
\setlocationattributes
\attribute\referenceattribute\lastreferenceattribute
\global\lastsavedreferenceattribute\lastreferenceattribute
@@ -1182,9 +1245,9 @@
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
+ \ctxcommand{doifelsereference("\referenceprefix","#label",\extrareferencearguments)}%
{\expandtexincurrentreference
- \ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}%
+ \ctxcommand{injectcurrentreference(\number\ht\strutbox,\number\dp\strutbox)}%
\setlocationattributes
\setstrut % can be option
\global\lastsavedreferenceattribute\lastreferenceattribute
@@ -1205,9 +1268,9 @@
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
+ \ctxcommand{doifelsereference("\referenceprefix","#label",\extrareferencearguments)}%
{\expandtexincurrentreference
- \ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}%
+ \ctxcommand{injectcurrentreference(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}%
\setlocationattributes
\global\lastsavedreferenceattribute\lastreferenceattribute
\attribute\referenceattribute\lastreferenceattribute
@@ -1226,7 +1289,7 @@
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
+ \ctxcommand{injectreference("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
\setlocationattributes
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
@@ -1243,7 +1306,7 @@
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
+ \ctxcommand{injectreference("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
\setlocationcolorspec{#resolver}% no consequence for strut
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
@@ -1260,7 +1323,7 @@
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
+ \ctxcommand{injectreference("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
\hbox attr \referenceattribute \lastreferenceattribute {#content}%
@@ -1276,9 +1339,9 @@
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
+ \ctxcommand{doifelsereference("\referenceprefix","#label",\extrareferencearguments)}%
{\expandtexincurrentreference
- \ctxlua{structures.references.injectcurrentset(nil,nil)}%
+ \ctxcommand{injectcurrentreference(nil,nil)}%
\setlocationattributes
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
@@ -1298,8 +1361,8 @@
\ht\scratchbox#height%
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
- \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
- {\ctxlua{structures.references.injectcurrentset(nil,nil)}%
+ \ctxcommand{doifelsereference("\referenceprefix","#label",\extrareferencearguments)}%
+ {\ctxcommand{injectcurrentreference(nil,nil)}%
\global\lastsavedreferenceattribute\lastreferenceattribute
\hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}}
{\box\scratchbox}%
@@ -1386,14 +1449,18 @@
%D
%D \showsetup{setupurl}
-\unexpanded\def\setupurl
- {\dodoubleargument\getparameters[\??ur]}
+\installcorenamespace{url}
+
+\installdirectcommandhandler \??url {url}
+
+\setupurl
+ [\c!style=\v!type,
+ \c!color=]
\unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua)
{\dontleavehmode
\begingroup
- \dousestyleparameter\@@urstyle
- \dousecolorparameter\@@urcolor
+ \useurlstyleandcolor\c!style\c!color
\hyphenatedurl{\ctxcommand{geturl("#label")}}%
\endgroup}
@@ -1425,14 +1492,13 @@
\def\strc_references_do_special_from[#label]%
{\dontleavehmode
- \goto{\ctxlua{structures.references.from("#label")}}[fileorurl(#label)]}
+ \goto{\ctxcommand{from("#label")}}[fileorurl(#label)]}
\def\dofromurldescription#content% called at the lua end
{#content}
\def\dofromurlliteral#content% called at the lua end
- {\dousestyleparameter\@@urstyle
- \dousecolorparameter\@@urcolor
+ {\useurlstyleandcolor\c!style\c!color
\hyphenatedurl{#content}}
\let\dofromfiledescription\dofromurldescription
@@ -1463,21 +1529,21 @@
% also lua, like urls and files
-\unexpanded\def\setupprograms
- {\dodoubleargument\getparameters[\??pr]}
+\installcorenamespace{programs}
+
+\installdirectcommandhandler \??programs {programs}
\unexpanded\def\defineprogram
{\dotripleargument\strc_references_define_program}
\def\strc_references_define_program[#name][#program][#description]%
- {\ctxlua{structures.references.programs.define("#name","#program","#description")}}
+ {\ctxcommand{defineprogram("#name","#program","#description")}}
\def\program[#name]% incompatible, more consistent, hardy used anyway
{\dontleavehmode
\begingroup
- \dousestyleparameter\@@prstyle
- \dousecolorparameter\@@prcolor
- \ctxlua{structures.references.programs.get("#name","\@@pralternative","\@@prspace")}%
+ \useprogramsstyleandcolor\c!style\c!color
+ \ctxcommand{getprogram("#name","\directprogramsparameter\c!alternative","\directprogramsparameter\c!space")}%
\endgroup}
%D As we can see, we directly use the special reference
@@ -1571,7 +1637,11 @@
\setbox\scratchbox\hbox{#text}% to be solved some day
\ifdim\wd\scratchbox>\zeropoint
\unhbox\scratchbox
- \doifsomething\@@rfseparator{\removeunwantedspaces\@@rfseparator}% remove is new
+ \edef\p_separator{\referencingparameter\c!separator}%
+ \ifx\p_separator\empty \else
+ \removeunwantedspaces % remove is new
+ \p_separator
+ \fi
\else
\unhbox\scratchbox
\fi
@@ -1598,10 +1668,6 @@
\c!separator=\nonbreakablespace,
\c!export=\v!no]
-\setupurl
- [\c!style=\v!type,
- \c!color=]
-
\setupprograms
[\c!directory=,
\c!style=\v!type,
@@ -1699,7 +1765,9 @@
% todo: parameterhandler
-\def\getreferencestructureprefix#kind#name#category%
+\installcorenamespace{referencingprefix}
+
+\def\getreferencestructureprefix#kind#name#category% name will change
{{
prefix = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefix",
separatorset = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixseparatorset",
@@ -1715,22 +1783,22 @@
\def\strc_references_setup_reference_structure_prefix[#kind][#category][#settings]%
{\ifthirdargument
- \getparameters[\??rf:\c!prefix:#kind:#category][#settings]%
+ \getparameters[\??referencingprefix#kind:#category][#settings]%
\else\ifsecondargument
- \getparameters[\??rf:\c!prefix::#kind][#category]%
+ \getparameters[\??referencingprefix:#kind][#category]%
\fi\fi}
\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
+ {\ifcsname\??referencingprefix#name:#category#parameter\endcsname
+ \csname\??referencingprefix#name:#category#parameter\endcsname
+ \else\ifcsname\??referencingprefix#kind:#category#parameter\endcsname
+ \csname \??referencingprefix#kind:#category#parameter\endcsname
+ \else\ifcsname\??referencingprefix:#category#parameter\endcsname
+ \csname \??referencingprefix:#category#parameter\endcsname
\fi\fi\fi}
\def\currentreferencedefault
- {\ctxlua{structures.references.filter("default",\ctxlua{structures.references.getcurrentprefixspec("\v!default")})}}
+ {\ctxcommand{filterdefaultreference()}}
%D Not all support is visible by looking at the \TEX\ code; here is one of those:^
%D
diff --git a/tex/context/base/strc-reg.lua b/tex/context/base/strc-reg.lua
index 6da58345b..23609cfd9 100644
--- a/tex/context/base/strc-reg.lua
+++ b/tex/context/base/strc-reg.lua
@@ -266,6 +266,10 @@ local function preprocessentries(rawdata)
end
rawdata.entries = nil
end
+ local seeword = rawdata.seeword
+ if seeword then
+ seeword.processor, seeword.text = splitprocessor(seeword.text or "")
+ end
end
function registers.store(rawdata) -- metadata, references, entries
@@ -826,10 +830,11 @@ function registers.flush(data,options,prefixspec,pagespec)
context.startregisterseewords()
for i=1,nt do
local entry = t[i]
- local processor = entry.processors and entry.processors[1] or ""
+ local seeword = entry.seeword
+ local seetext = seeword.text or ""
+ local processor = seeword.processor or (entry.processors and entry.processors[1]) or ""
local seeindex = entry.references.seeindex or ""
- local seeword = entry.seeword.text or ""
- context.registerseeword(i,n,processor,0,seeindex,seeword)
+ context.registerseeword(i,n,processor,0,seeindex,seetext)
end
context.stopregisterseewords()
end
diff --git a/tex/context/base/strc-reg.mkiv b/tex/context/base/strc-reg.mkiv
index e36556949..3940594c3 100644
--- a/tex/context/base/strc-reg.mkiv
+++ b/tex/context/base/strc-reg.mkiv
@@ -19,12 +19,7 @@
% todo: tag:: becomes rendering
% todo: language, character, linked, location
-
-%D Helper:
-
-% \def\doflushatpar{\ifvmode\expandafter\dogotopar\else\expandafter\firstofoneargument\fi}
-
-\def\doflushatpar{\ifvmode\expandafter\flushatnextpar\else\expandafter\firstofoneargument\fi}
+% todo: fonts etc at sublevels (already defined)
% \starttext
% \placeregister[index]
@@ -34,9 +29,6 @@
% test \index{aa} test \setregisterentry[index][label=y] test \page test \page test \page test \finishregisterentry[index][label=y,entries=yy]
% \stoptext
-% In plaats van + kan een & worden gebruikt. Ook kan als
-% eerste karakter worden opgegeven wat de scheider is.
-%
% \index {entry}
% \index[key] {entry}
% \index[pageclass::] {entry}
@@ -46,52 +38,34 @@
% \index[pageclass::] {textclass::entry}
% \index[pageclass::key]{textclass::entry}
-%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
-
-% \def\registerparameter#1{\csname\??id\currentregister#1\endcsname}
-
-\def\detokenizedregisterparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??id#1\endcsname}} % always root
+% tzt variant with n entries, parameters and userdata (altnum)
-\def\registerparameter #1{\csname\doregisterparameter{\??id\currentregister}{#1}\endcsname}
-\def\registerparameterhash#1{\doregisterparameterhash {\??id\currentregister}#1}
+\installcorenamespace{register}
-\def\doregisterparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doregisterparentparameter \csname#1\s!parent\endcsname{#2}\fi}
-\def\doregisterparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doregisterparentparameterhash\csname#1\s!parent\endcsname{#2}\fi}
+\installcommandhandler\??register {register} \??register
-\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}
+\let\strc_registers_setup_saved\setupregister
-\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}
+\unexpanded\def\setupregister % maybe we should drop the plural form
+ {\dotripleempty\strc_registers_setup}
-%D Setup:
-
-\newtoks\everysetupregister
-
-\unexpanded\def\setupregisters
- {\dotripleempty\dosetupregisters}
-
-\def\dosetupregisters[#1][#2][#3]%
+\def\strc_registers_setup[#1][#2][#3]%
{\ifthirdargument
- \def\dodosetupregister##1{\getparameters[\??id##1#2][#3]}%
- \processcommalist[#1]\dodosetupregister
+ \def\strc_registers_setup_step##1{\strc_registers_setup_saved[#1:##1][#3]}%
+ \processcommalist[#2]\strc_registers_setup_step
\else\ifsecondargument
- \def\dodosetupregister##1{\edef\currentregister{##1}\getparameters[\??id##1][#2]\the\everysetupregister}%
- \processcommalist[#1]\dodosetupregister
+ \strc_registers_setup_saved[#1][#2]%
\else
- \getparameters[\??id][#1]%
+ \strc_registers_setup_saved[#1]%
\fi\fi}
-\let\setupregister\setupregisters
+\unexpanded\def\setupregisters
+ {\dosingleempty\strc_registers_setup_root}
+
+\def\strc_registers_setup_root[#1]%
+ {\strc_registers_setup_saved[#1]\relax}
-\setupregisters
+\setupregister
[\c!n=2,
\c!balance=\v!yes, % \v!no komt niet zo vaak voor
\c!align=\v!flushleft,
@@ -102,7 +76,7 @@
\c!compress=\v!no,
\c!interaction=\v!pagenumber,
\c!alternative=\v!a,
- \c!distance=1em,
+ \c!distance=\emwidth,
\c!style=\v!bold,
\c!pagestyle=\v!slanted,
\c!indicator=\v!yes,
@@ -115,7 +89,7 @@
\c!unknownreference=\v!empty,
\c!prefix=\v!both,
%\c!expansion=,
-%\c!xmlsetup=,
+ %\c!xmlsetup=,
\c!pagenumber=\v!yes,
\c!pageprefixconnector=\endash,
\c!pagesegments=2:2,
@@ -125,48 +99,63 @@
\c!numberorder=\v!numbers, % \v!characters
\s!language=\currentmainlanguage]%
-%D Definition:
+% yes or no shared ?
-\unexpanded\def\defineregister
- {\dodoubleargument\dodefineregister}
+\setupregister
+ [\c!label=,
+ \c!entries=,
+ \c!alternative=]
-\def\dodefineregister[#1][#2]% #2?
- {\setupregister[#1][\s!parent=\??id]%
- \ctxlua{structures.registers.define('#1')}%
- \presetheadtext[#1=\Word{#1}]%
- \setuvalue{#1}{\dodoubleempty\doregister[#1]}%
- \setuvalue{\e!see#1}{\dodoubleempty\doseeregister[#1]}%
-% \setuvalue{\e!coupled#1}{\dolinkedregister{#1}}%
- \setvalue{\e!place#1}{\placeregister[#1]}%
- \setvalue{\e!complete#1}{\completeregister[#1]}%
- \setvalue{\e!setup#1\e!endsetup}[##1]{\getparameters[\??id#1][##1]}}
+%D \starttyping
+%D \setupregister[index][1][textcolor=darkred]
+%D \setupregister[index][2][textcolor=darkgreen,textstyle=bold]
+%D
+%D \placeregister[index][n=1] \blank[3*big]
+%D
+%D test \index{test+one} test \index{test+two} more \index{more}
+%D \stoptyping
-%D Registering:
+\newconditional\c_strc_registers_defining
-\newif\ifwritetoregister \writetoregistertrue
+\ifdefined\Word \else \unexpanded\def\Word#1{#1} \fi
-% tzt variant met n entries, parameters en userdata (altnum)
+\appendtoks
+ \ifconditional\c_strc_registers_defining \else
+ \settrue\c_strc_registers_defining
+ \ctxlua{structures.registers.define('\currentregister')}%
+ \normalexpanded{\presetheadtext[\currentregister=\Word{\currentregister}]}%
+ \setuevalue{\currentregister}{\dodoubleempty\strc_registers_insert_entry[\currentregister]}%
+ \setuevalue{\e!see\currentregister}{\dodoubleempty\strc_registers_insert_see[\currentregister]}%
+ %setuevalue{\e!coupled\currentregister}{\dolinkedregister{\currentregister}}%
+ % historic ballast
+ \setuevalue{\e!place\currentregister}{\placeregister[\currentregister]}%
+ \setuevalue{\e!complete\currentregister}{\completeregister[\currentregister]}%
+ \setuevalue{\e!setup\currentregister\e!endsetup}{\setupregister[\currentregister]}%
+ \dorecurse\plusthree {% weird, expanded should not be needed
+ \normalexpanded{\defineregister[\currentregister:\recurselevel][\currentregister]}%
+% \defineregister[\currentregister:\recurselevel][\currentregister]%
+ \letregisterparameter{\c!entries:\recurselevel}\empty % needed as we use detokenize (ok, we can
+ \letregisterparameter{\c!keys :\recurselevel}\empty % avoid it, but it's faster too)
+ }%
+ %
+ \setfalse\c_strc_registers_defining
+ \fi
+\to \everydefineregister
-\getparameters
- [\??id]
- [\c!label=,
- \c!entries=,
- \c!entries:1=,\c!entries:2=,\c!entries:3=,
- \c!keys:1=,\c!keys:2=,\c!keys:3=,
- \c!alternative=]
+%D Registering:
-\def\doregisterstructurepageregister
+\def\strc_registers_register_page_entry
{\iftrialtypesetting
\expandafter\gobblethreearguments
\else
- \expandafter\dodoregisterstructurepageregister
+ \expandafter\strc_registers_register_page_entry_indeed
\fi}
-\def\dodoregisterstructurepageregister#1#2#3% register data userdata
+\def\strc_registers_register_page_entry_indeed#1#2#3% register data userdata
{\begingroup
\edef\currentregister{#1}%
- %getparameters[\??id][\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
- \getparameters[\??id][#2]%
+ %\setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
+ \setupcurrentregister[#2]%
\edef\currentregisterlabel {\registerparameter\c!label}%
\edef\currentregisterexpansion{\registerparameter\c!expansion}%
\edef\currentregisterownnumber{\registerparameter\c!ownnumber}%
@@ -245,7 +234,7 @@
section = structures.sections.currentid(), % hm, why then not also lastsection the same way
label = "\currentregisterlabel",
},
-% \ifx\currentregisterentries\empty \else
+ % \ifx\currentregisterentries\empty \else
entries = {
% we need a special one for xml, this is just a single one
\ifx\currentregisterentries\empty
@@ -259,10 +248,10 @@
\!!bs\currentregisterkeys\!!es,
\fi
},
-% \fi
+ % \fi
userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
}
- } }%
+ }}%
\ctxlua{structures.references.setinternalreference(nil,nil,\nextinternalreference)}%
\ifx\currentregisterownnumber\v!yes
\glet\currentregistersynchronize\relax
@@ -275,45 +264,51 @@
\attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
\endgroup}
-\def\doregister[#1][#2]%
+\unexpanded\def\strc_registers_insert_entry[#1][#2]%
{\def\currentregister{#1}%
- \doifelse{\registerparameter\c!ownnumber}\v!yes\dodoregister\donoregister{#1}{#2}}
+ \doifelse{\registerparameter\c!ownnumber}\v!yes
+ \strc_registers_insert_entry_yes
+ \strc_registers_insert_entry_nop
+ {#2}}
+
+\def\strc_registers_insert_entry_nop#1#2%
+ {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}}
-\def\donoregister #1#2#3{\doflushatpar{\doregisterstructurepageregister{#1}{\c!keys={#2},\c!entries={#3}}{}}}
-\def\dodoregister#1#2#3#4{\doflushatpar{\doregisterstructurepageregister{#1}{\c!keys={#2},\c!alternative=#3,\c!entries={#4}}{}}}
+\def\strc_registers_insert_entry_yes#1#2#3%
+ {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}}
-\unexpanded\def\startregister{\doquadrupleempty\dostartregister}
-\unexpanded\def\stopregister {\dodoubleargument\dostopregister}
+\unexpanded\def\startregister{\doquadrupleempty\strc_registers_start_entry}
+\unexpanded\def\stopregister {\dodoubleargument\strc_registers_stop_entry}
% a synonym, so that we can nest with overlap without syntax check problems
\let\openregisterrange \startregister
\let\closeregisterrange\stopregister
-\def\dostartregister[#1][#2][#3][#4]#5%
+\def\strc_registers_start_entry[#1][#2][#3][#4]#5%
{\iffourthargument
% #1=register #2=tag #3=own #4=sortkey #5=entry
- \doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}%
+ \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!alternative=#3,\c!keys={#4},\c!entries={#5}}{}}%
\else
% #1=register #2=tag #3=sortkey #5=entry
- \doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}%
+ \doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,\c!keys={#3},\c!entries={#5}}{}}%
\fi}
-\def\dostopregister[#1][#2]%
+\def\strc_registers_stop_entry[#1][#2]%
{\normalexpanded{\ctxlatelua{structures.registers.extend("#1","#2")}}}
-\def\setregisterentry {\dotripleempty\dosetregisterentry}
-\def\finishregisterentry{\dotripleempty\dofinishregisterentry}
+\def\setregisterentry {\dotripleempty\strc_registers_set_entry}
+\def\finishregisterentry{\dotripleempty\strc_registers_finish_entry}
% not yet document, not sure if this will stay:
-\def\dosetregisterentry [#1][#2][#3]{\doflushatpar{\doregisterstructurepageregister{#1}{#2}{#3}}}
-\def\dofinishregisterentry[#1][#2][#3]{\dofinishregisterstructurepageregister{#1}{#2}{#3}}
+\def\strc_registers_set_entry [#1][#2][#3]{\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}}
+\def\strc_registers_finish_entry[#1][#2][#3]{\strc_registers_finish_entry_indeed{#1}{#2}{#3}}
-\def\dofinishregisterstructurepageregister#1#2#3% register data userdata
+\def\strc_registers_finish_entry_indeed#1#2#3% register data userdata
{\begingroup
\edef\currentregister{#1}%
- \getparameters[\??id][\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
+ \setupcurrentregister[\c!entries=,\c!label=,\c!keys=,\c!alternative=,#2]%
\edef\currentregisterlabel {\registerparameter\c!label}%
\edef\currentregisterexpansion{\registerparameter\c!expansion}%
\edef\currentregisterownnumber{\registerparameter\c!ownnumber}%
@@ -336,7 +331,7 @@
\normalexpanded{\ctxlua{structures.registers.extend("\currentregister","\currentregisterlabel", {
metadata = {
\ifx\currentregisterownnumber\v!yes
- own = "\registerparameter\c!alternative", % can be used instead of pagenumber
+ own = "\registerparameter\c!alternative", % can be used instead of pagenumber
\fi
},
userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
@@ -353,7 +348,8 @@
},
entries = {
% we need a special one for xml, this is just a single one
- \!!bs\currentregisterentries\!!es, \!!bs\currentregisterkeys\!!es
+ \!!bs\currentregisterentries\!!es,
+ \!!bs\currentregisterkeys\!!es
},
userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
})
@@ -377,29 +373,32 @@
% \placeregister[index][n=1]
% \stoptext
-\def\setstructurepageregister{\dotripleempty\dosetstructurepageregister}
+% some overlap wit previous
+
+\unexpanded\def\setstructurepageregister
+ {\dotripleempty\strc_registers_set}
-\def\dosetstructurepageregister[#1][#2][#3]% [register][settings][userdata]
- {\doflushatpar{\doregisterstructurepageregister{#1}{#2}{#3}}}
+\def\strc_registers_set[#1][#2][#3]% [register][settings][userdata]
+ {\doflushatpar{\strc_registers_register_page_entry{#1}{#2}{#3}}}
-\unexpanded\def\startstructurepageregister{\doquadrupleempty\dostartstructurepageregister}
-\unexpanded\def\stopstructurepageregister {\dodoubleargument\dostopstructurepageregister}
+\unexpanded\def\startstructurepageregister{\doquadrupleempty\strc_registers_start}
+\unexpanded\def\stopstructurepageregister {\dodoubleargument\strc_registers_stop}
\let\openstructurepageregisterrange \startstructurepageregister
\let\closestructurepageregisterrange\stopstructurepageregister
-\def\dostartstructurepageregister[#1][#2][#3][#4]% [register][tag][settings][userdata]
- {\doflushatpar{\doregisterstructurepageregister{#1}{\c!label=#2,#3}{#4}}}
+\def\strc_registers_start[#1][#2][#3][#4]% [register][tag][settings][userdata]
+ {\doflushatpar{\strc_registers_register_page_entry{#1}{\c!label=#2,#3}{#4}}}
-\def\dostopstructurepageregister[#1][#2]%
+\def\strc_registers_stop[#1][#2]%
{\normalexpanded{\ctxlatelua{structures.registers.extend("#1","#2")}}}
% So far.
-\def\doseeregister[#1][#2]#3#4%
- {\doflushatpar{\doprocessseeregister{#1}{#2}{#3}{#4}}}
+\unexpanded\def\strc_registers_insert_see[#1][#2]#3#4%
+ {\doflushatpar{\strc_registers_insert_see_indeed{#1}{#2}{#3}{#4}}}
-\def\doprocessseeregister#1#2#3#4% register key entry seeword
+\def\strc_registers_insert_see_indeed#1#2#3#4% register key entry seeword
{\begingroup
\edef\currentregister{#1}%
\edef\currentregisterexpansion{\registerparameter\c!expansion}%
@@ -434,10 +433,11 @@
},
entries = {
% we need a special one for xml, this is just a single one
- "\currentregisterentries", "#2"
+ \!!bs\currentregisterentries\!!es,
+ \!!bs#2\!!es
},
seeword = {
- text = "\currentregisterseeword"
+ text = \!!bs\currentregisterseeword\!!es
},
}
}}%
@@ -450,9 +450,9 @@
\let\utilityregisterlength\!!zerocount
\def\determineregistercharacteristics
- {\dodoubleempty\dodetermineregistercharacteristics}
+ {\dodoubleempty\strc_registers_determine_characteristics}
-\def\dodetermineregistercharacteristics[#1][#2]%
+\def\strc_registers_determine_characteristics[#1][#2]%
{\begingroup
\edef\currentregister{#1}%
\setupregister[\currentregister][#2]%
@@ -476,67 +476,85 @@
\to \everyplaceregister
\unexpanded\def\placeregister
- {\dodoubleempty\doplaceregister}
+ {\dodoubleempty\strc_registers_place}
-\def\doplaceregister[#1][#2]%
+\def\strc_registers_place[#1][#2]%
{\iffirstargument
\begingroup
-% \forgetall
+ %\forgetall
\edef\currentregister{#1}%
\setupregister[\currentregister][#2]%
\the\everyplaceregister
- \startcolumns
- [\c!n=\registerparameter\c!n,
- \c!balance=\registerparameter\c!balance,
- \c!align=\registerparameter\c!align,
- \c!tolerance=\registerparameter\c!tolerance]%
- \startpacked[\v!blank]%
- \ctxlua{structures.registers.process('\currentregister',{
- language = "\registerparameter\s!language",
- method = "\registerparameter\c!method",
- numberorder = "\registerparameter\c!numberorder",
- compress = "\registerparameter\c!compress",
- criterium = "\registerparameter\c!criterium",
- },
- {
-% prefix = "\registerparameter\c!pageprefix",
- separatorset = "\registerparameter\c!pageprefixseparatorset",
- conversionset = "\registerparameter\c!pageprefixconversionset",
- starter = \!!bs\registerparameter\c!pageprefixstarter\!!es,
- stopper = \!!bs\registerparameter\c!pageprefixstopper\!!es,
- set = "\registerparameter\c!pageprefixset",
- segments = "\registerparameter\c!pageprefixsegments",
- connector = \!!bs\registerparameter\c!pageprefixconnector\!!es,
- },
- {
- prefix = "\registerparameter\c!pageprefix",
- separatorset = "\registerparameter\c!pageseparatorset",
- conversionset = "\registerparameter\c!pageconversionset",
- starter = \!!bs\registerparameter\c!pagestarter\!!es,
- stopper = \!!bs\registerparameter\c!pagestopper\!!es,
- segments = "\registerparameter\c!pagesegments",
- }
- )}%
- \stoppacked
- \stopcolumns
+ \ifnum\registerparameter\c!n>\plusone
+ \startcolumns
+ [\c!n=\registerparameter\c!n,
+ \c!balance=\registerparameter\c!balance,
+ \c!align=\registerparameter\c!align,
+ \c!tolerance=\registerparameter\c!tolerance]%
+ \strc_registers_place_indeed
+ \stopcolumns
+ \else
+ \strc_registers_place_indeed
+ \fi
\endgroup
\fi}
-\def\dolimitedregisterentry#1{\limitatetext{#1}\currentregistermaxwidth\unknown}%
+\def\strc_registers_place_columns
+ {\startcolumns
+ [\c!n=\registerparameter\c!n,
+ \c!balance=\registerparameter\c!balance,
+ \c!align=\registerparameter\c!align,
+ \c!tolerance=\registerparameter\c!tolerance]%
+ \startpacked[\v!blank]%
+ \strc_registers_place_indeed
+ \stoppacked
+ \stopcolumns}
+
+\def\strc_registers_place_normal
+ {\startpacked[\v!blank]%
+ \strc_registers_place_indeed
+ \stoppacked}
+
+\def\strc_registers_place_indeed
+ {\ctxlua{structures.registers.process('\currentregister',{
+ language = "\registerparameter\s!language",
+ method = "\registerparameter\c!method",
+ numberorder = "\registerparameter\c!numberorder",
+ compress = "\registerparameter\c!compress",
+ criterium = "\registerparameter\c!criterium",
+ },{
+ separatorset = "\registerparameter\c!pageprefixseparatorset",
+ conversionset = "\registerparameter\c!pageprefixconversionset",
+ starter = \!!bs\registerparameter\c!pageprefixstarter\!!es,
+ stopper = \!!bs\registerparameter\c!pageprefixstopper\!!es,
+ set = "\registerparameter\c!pageprefixset",
+ segments = "\registerparameter\c!pageprefixsegments",
+ connector = \!!bs\registerparameter\c!pageprefixconnector\!!es,
+ },{
+ prefix = "\registerparameter\c!pageprefix",
+ separatorset = "\registerparameter\c!pageseparatorset",
+ conversionset = "\registerparameter\c!pageconversionset",
+ starter = \!!bs\registerparameter\c!pagestarter\!!es,
+ stopper = \!!bs\registerparameter\c!pagestopper\!!es,
+ segments = "\registerparameter\c!pagesegments",
+ })}}
+
+\def\strc_registers_limited_entry#1%
+ {\limitatetext{#1}\currentregistermaxwidth\unknown}%
\appendtoks
\edef\currentregistermaxwidth{\registerparameter\c!maxwidth}%
\ifx\currentregistermaxwidth\empty
\let\limitedregisterentry\firstofoneargument
\else
- \let\limitedregisterentry\dolimitedregisterentry
+ \let\limitedregisterentry\strc_registers_limited_entry
\fi
\to \everyplaceregister
-\def\completeregister
- {\dodoubleempty\docompleteregister}
+\unexpanded\def\completeregister
+ {\dodoubleempty\strc_registers_complete}
-\def\docompleteregister[#1][#2]%
+\def\strc_registers_complete[#1][#2]%
{\iffirstargument
\begingroup
\edef\currentregister{#1}%
@@ -546,7 +564,7 @@
\stopnamedsection
\endgroup
\fi}
-
+
% test case for collapsing (experimental, for Steffen Wolfrum)
%
% \starttext
@@ -565,37 +583,36 @@
% xxxx \index{xxxx}
% todo \index{todo}
% \stoptext
-
+
%D Character rendering (sections):
+\installcorenamespace{registerindicator}
+
\def\defaultregistercharacter#1%
- {\doifsomething{#1}
- {\doifnot{#1}\s!unknown
- {\doifelse{\registerparameter\c!indicator}\v!yes
- {\doregistercharacter{#1}}
- {\noregistercharacter{#1}}}}}
-
-% \def\doregistercharacter#1%
-% {\expandcheckedcsname % why no \executeifdefined
-% {\??id:\c!indicator:}%
-% {\registerparameter\c!alternative}%
-% {a}%
-% {#1}}
-
-\def\doregistercharacter#1%
- {\expandcheckedcsname % why no \executeifdefined
- {\??id:\c!indicator:}%
- {\registerparameter\c!alternative}%
- {a}%
- {#1}}
-
-\def\noregistercharacter#1%
+ {\edef\currentregistercharacter{#1}%
+ \ifx\currentregistercharacter\empty
+ % skip
+ \else\ifx\currentregistercharacter\s!unknown
+ % skip
+ \else
+ \edef\p_indicator{\registerparameter\c!indicator}%
+ \ifx\p_indicator\v!yes
+ \strc_registers_place_character_yes
+ \else
+ \strc_registers_place_character_nop
+ \fi
+ \fi\fi}
+
+\def\strc_registers_place_character_yes
+ {\expandcheckedcsname\??registerindicator{\registerparameter\c!alternative}\v!a{\currentregistercharacter}}
+
+\def\strc_registers_place_character_nop
{\registerparameter\c!before
\goodbreak}
% a = <before> <goodbreak> <character> <par> <after> <nobreak>
-\setvalue{\??id:\c!indicator:a}#1%
+\setvalue{\??registerindicator a}#1%
{\registerparameter\c!before
% bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight
\begingroup
@@ -607,13 +624,14 @@
\fi
\registerparameter\c!command{#1}%
\endgroup
+ \blank[\v!samepage]%
\registerparameter\c!after
\par
\nobreak}
% b = <goodbreak> <before> <character> <after> <nobreak>
-\setvalue{\??id:\c!indicator:b}#1% will be shared with a
+\setvalue{\??registerindicator b}#1% will be shared with a
{\registerparameter\c!before
\begingroup
\useregisterstyleandcolor\c!style\c!color
@@ -627,9 +645,9 @@
\registerparameter\c!after
\nobreak}
-\setvalue{\??id:\c!indicator:A}#1{\getvalue{\??id:\c!indicator:a}{\WORD{#1}}}
-\setvalue{\??id:\c!indicator:B}#1{\getvalue{\??id:\c!indicator:b}{\WORD{#1}}}
-
+\setvalue{\??registerindicator A}#1{\getvalue{\??registerindicator a}{\WORD{#1}}}
+\setvalue{\??registerindicator B}#1{\getvalue{\??registerindicator b}{\WORD{#1}}}
+
%D The following macros are the interface to the rendering. These are
%D generated by \LUA. This might change.
@@ -637,9 +655,13 @@
%D placeindex as then flushing takes place inside the index. Took me hours
%D to notice that.
+\newconditional\c_strc_registers_page_done
+\newdimen \d_strc_registers_distance
+
\unexpanded\def\startregisteroutput
{\endgraf
\begingroup
+ \d_strc_registers_distance\registerparameter\c!distance\relax
\dostarttagged\t!register\currentregister
\forgeteverypar
\forgetparindent
@@ -654,9 +676,13 @@
{\endgraf
\begingroup
\dostarttagged\t!registerentries\empty
+ \let\savedcurrentregister\currentregister
+ \edef\currentregister{\currentregister:#1}%
\useregisterstyleandcolor\c!textstyle\c!textcolor
- \advance\leftskip\numexpr#1-1\relax\dimexpr\registerparameter\c!distance\relax
- \hangindent\registerparameter\c!distance\hangafter\plusone}
+ \advance\leftskip\numexpr#1-\plusone\relax\dimexpr\d_strc_registers_distance\relax
+ \hangindent\registerparameter\c!distance\relax
+ \hangafter\plusone
+ \let\currentregister\savedcurrentregister}
\unexpanded\def\stopregisterentries
{\endgraf
@@ -673,12 +699,10 @@
{\dostoptagged
\endgraf}
-\newconditional\registerpagedone
-
\unexpanded\def\startregisterpages
{\begingroup
\dostarttagged\t!registerpages\empty
- \setfalse\registerpagedone
+ \setfalse\c_strc_registers_page_done
\useregisterstyleandcolor\c!pagestyle\c!pagecolor}
\unexpanded\def\stopregisterpages
@@ -688,7 +712,7 @@
\unexpanded\def\startregisterseewords
{\ifhmode\crlf\fi
\begingroup
- \setfalse\registerpagedone
+ \setfalse\c_strc_registers_page_done
\dostarttagged\t!registerpage\empty
\useregisterstyleandcolor\c!pagestyle\c!pagecolor}
@@ -696,15 +720,16 @@
{\dostoptagged
\endgroup}
-\def\registerpageseparator% todo: , configurable
- {\ifconditional\registerpagedone
+\unexpanded\def\registerpageseparator% todo: , configurable
+ {\ifconditional\c_strc_registers_page_done
\registerpageseparatorsymbol
\else
- \hskip\registerparameter\c!distance\relax
- \settrue\registerpagedone
+ \hskip\d_strc_registers_distance\relax
+ \settrue\c_strc_registers_page_done
\fi}
-\def\registeronepagerangeseparator{|\endash|}
+\unexpanded\def\registeronepagerangeseparator
+ {|\endash|}
\def\withregisterpagecommand#1#2#3#4%
{\def\currentregisterpageindex{#2}%
@@ -714,13 +739,13 @@
\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
\fi}
-\def\registeronepage#1#2#3#4% #1:processor content
+\unexpanded\def\registeronepage#1#2#3#4% #1:processor content
{\registerpageseparator
\dostarttagged\t!registerpage\empty
\withregisterpagecommand{#1}{#2}{#3}{#4}%
\dostoptagged}
-\def\registerpagerange#1#2#3#4#5#6#7% #1:processor content, content todo: -- configurable
+\unexpanded\def\registerpagerange#1#2#3#4#5#6#7% #1:processor content, content todo: -- configurable
{\registerpageseparator
\dostarttagged\t!registerpagerange\empty
\dostarttagged\t!registerfrompage\empty
@@ -732,7 +757,7 @@
\dostoptagged
\dostoptagged}
-\def\doapplyregisterentrycommand#1#2% processor text
+\unexpanded\def\doapplyregisterentrycommand#1#2% processor text
{\dostarttagged\t!registerentry\empty
\ifx\currentregisterseeindex\empty \else
\dontleavehmode
@@ -741,7 +766,7 @@
\applyprocessor{#1}{\registerparameter\c!textcommand{\limitedregisterentry{\registerparameter\c!deeptextcommand{#2}}}}%
\dostoptagged}
-\def\defaultregisterentry#1#2#3#4% #1:processor #2:internal #3:seeindex #4:word
+\unexpanded\def\defaultregisterentry#1#2#3#4% #1:processor #2:internal #3:seeindex #4:word
{\def\currentregisterpageindex{#2}%
\iflocation
\def\currentregisterseeindex{#3}%
@@ -761,11 +786,11 @@
\goto{\applyprocessor{#1}{#2}}[seeindex:\currentregisterseeindex]%
\fi}
-\def\defaultregisterseeword#1#2#3#4#5#6% i n #3:processor #4:internal #5:seeindex #6:word
+\unexpanded\def\defaultregisterseeword#1#2#3#4#5#6% i n #3:processor #4:internal #5:seeindex #6:word
{%\registerpageseparator
\def\currentregisterpageindex{#4}%
\dostarttagged\t!registersee\empty
- \settrue\registerpagedone
+ \settrue\c_strc_registers_page_done
\iflocation
\def\currentregisterseeindex{#5}%
\else
@@ -805,41 +830,44 @@
% not yet ok : new internal handler names
-\def\registerpagebuttonsymbol{\vrule\!!width1em\!!height1ex\!!depth\zeropoint\relax}
+\unexpanded\def\registerpagebuttonsymbol
+ {\vrule\s!width\emwidth\s!height\exheight\s!depth\zeropoint\relax}
+
+\installcorenamespace{registersymbol}
-\setvalue{\??id:\c!symbol:\c!n}%
+\setvalue{\??registersymbol n}%
{\def\registerpageseparatorsymbol{, }}
-\setvalue{\??id:\c!symbol:\c!a}%
+\setvalue{\??registersymbol a}%
{\def\registerpageseparatorsymbol{, }} % now done via conversion
-\setvalue{\??id:\c!symbol:\v!none}%
+\setvalue{\??registersymbol\v!none}%
{\let\registerpageseparatorsymbol\empty
\let\registeronepage \gobblefourarguments
\let\registerpagerange \gobblesevenarguments}
-\setvalue{\??id:\c!symbol:1}%
+\setvalue{\??registersymbol 1}%
{\let\registerpageseparatorsymbol\space
- \def\registeronepage {\symbol[1]\gobblefourarguments}%
- \def\registerpagerange {\symbol[1]\gobblesevenarguments}}
+ \def\registeronepage {\symbol[1]\gobblefourarguments}%
+ \def\registerpagerange{\symbol[1]\gobblesevenarguments}}
-\setvalue{\??id:\c!symbol:2}%
+\setvalue{\??registersymbol 2}%
{\let\registerpageseparatorsymbol\space
- \def\registeronepage {\registerpagebuttonsymbol\gobblefourarguments}%
- \def\registerpagerange {\registerpagebuttonsymbol\gobblesevenarguments}}
+ \def\registeronepage {\registerpagebuttonsymbol\gobblefourarguments}%
+ \def\registerpagerange{\registerpagebuttonsymbol\gobblesevenarguments}}
\def\setregisterpagerendering
{\doifelse{\registerparameter\c!pagenumber}\v!no
{\let \currentregisterpagesymbol\v!none}
{\edef\currentregisterpagesymbol{\registerparameter\c!symbol}}%
\ifx\currentregisterpagesymbol\empty
- \csname\??id:\c!symbol:\c!n\endcsname
- \else\ifcsname\??id:\c!symbol:\currentregisterpagesymbol\endcsname
- \csname\??id:\c!symbol:\currentregisterpagesymbol\endcsname
+ \csname\??registersymbol n\endcsname
+ \else\ifcsname\??registersymbol\currentregisterpagesymbol\endcsname
+ \csname\??registersymbol\currentregisterpagesymbol\endcsname
\else
\let\registerpageseparatorsymbol\space
- \def\registeronepage {\registerparameter\c!symbol\gobblefourarguments}%
- \def\registerpagerange {\registerparameter\c!symbol\gobblesevenarguments}%
+ \def\registeronepage{\registerparameter\c!symbol\gobblefourarguments}%
+ \def\registerpagerange{\registerparameter\c!symbol\gobblesevenarguments}%
\fi\fi}
\appendtoks
@@ -853,6 +881,6 @@
\defineregister
[\v!index]
- [\v!indices]
+% [\v!indices]
\protect \endinput
diff --git a/tex/context/base/strc-ren.mkiv b/tex/context/base/strc-ren.mkiv
index b7b4224cd..d9cebc17f 100644
--- a/tex/context/base/strc-ren.mkiv
+++ b/tex/context/base/strc-ren.mkiv
@@ -15,7 +15,10 @@
\unprotect
-\newconstant\headtimingmode
+\newbox\b_strc_rendering_head
+
+\newdimen\d_strc_rendering_local_leftoffset
+\newdimen\d_strc_rendering_local_rightoffset
% Martin Kolarik's problem:
%
@@ -23,90 +26,57 @@
% \def\doTitle#1#2{\ruledvbox{\forgetall \hsize=4cm \ruledhbox{\ruledvtop{#1}\ruledvtop{#2}}}}
% \section{test test test test test test test test test test test test test test test test test}
-\newevery \everyheadstart \relax
+\newtoks\everyheadstart
-\unexpanded\def\setupheadcomponentfont#1#2%
+\unexpanded\def\strc_rendering_initialize_style_and_color
+ {\ifconditional\headisdisplay
+ \expandafter\strc_rendering_initialize_style_and_color_display
+ \else
+ \expandafter\strc_rendering_initialize_style_and_color_inline
+ \fi}
+
+\unexpanded\def\strc_rendering_initialize_style_and_color_display#1#2%
{\dontconvertfont
- \ifconditional\headisdisplay
- \edef\askedheadinterlinespace{\headparameter\c!interlinespace}%
- \ifx\askedheadinterlinespace\empty
- % here the interline space is only set when style sets no space
- \setfalse\fontattributeisset % use the currentfontparameter state instead
- \setfalse\interlinespaceisset
- \useheadstyleandcolor\c!style\c!color
- \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else
- \setupinterlinespace
- \fi \fi
- \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
- \useheadstyleandcolor\c!style\c!color
- \ifconditional\fontattributeisset
- \dosetupcheckedinterlinespace\askedheadinterlinespace
- \fi
- \setfalse\fontattributeisset
- \useheadstyleandcolor#1#2%
- \ifconditional\fontattributeisset
- \dosetupcheckedinterlinespace\askedheadinterlinespace
- \fi
- \fi
+ \edef\p_strc_rendering_interlinespace{\headparameter\c!interlinespace}%
+ \ifx\p_strc_rendering_interlinespace\empty
+ % here the interline space is only set when style sets no space
+ \setfalse\fontattributeisset % use the currentfontparameter state instead
+ \setfalse\interlinespaceisset
+ \useheadstyleandcolor\c!style\c!color\relax
+ \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else
+ \setupinterlinespace
+ \fi \fi
+ \setfalse\fontattributeisset
+ \useheadstyleandcolor#1#2\relax
+ \ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else
+ \setupinterlinespace
+ \fi \fi
\else
+ % here the set interline space overloads any other set space in the style
\setfalse\fontattributeisset
- \useheadstyleandcolor\c!style\c!color
+ \useheadstyleandcolor\c!style\c!color\relax
\ifconditional\fontattributeisset
- \setupspacing
+ \dosetupcheckedinterlinespace\p_strc_rendering_interlinespace
\fi
\setfalse\fontattributeisset
- \useheadstyleandcolor#1#2%
+ \useheadstyleandcolor#1#2\relax
\ifconditional\fontattributeisset
- \setupspacing
+ \dosetupcheckedinterlinespace\p_strc_rendering_interlinespace
\fi
\fi}
-\def\doplaceheadtextcomponent#1%
- {\begingroup
- \setupheadcomponentfont\c!textstyle\c!textcolor
- \headparameter\c!commandbefore
- \ifcsname\currentheadhash\c!deeptextcommand\endcsname
- \expandafter\let\expandafter\deepstructuretitlecommand\csname\currentheadhash\c!deeptextcommand\endcsname
- \fi
- \ifconditional\headisdisplay % \ifdisplaysectionhead
- % struts can be nilled with \setnostrut
- \headparameter\c!textcommand{\setstrut\begstrut#1\endstrut}%
- \xdef\localheadheight {\the\strutht}%
- \xdef\localheaddepth {\the\strutdp}%
- \xdef\localheadlineheight{\the\lineheight}%
- % == \globallet\localheaddepth\strutdepth
- \else
- \headparameter\c!textcommand{#1}%
- \fi
- \headparameter\c!commandafter
- \ifconditional\headisdisplay % \ifdisplaysectionhead
- \endgraf
- \fi
- \endgroup}
-
-\def\doplaceheadnumbercomponent#1%
- {\begingroup
- \setupheadcomponentfont\c!numberstyle\c!numbercolor
- \ifcsname\currentheadhash\c!deepnumbercommand\endcsname
- \expandafter\let\expandafter\deepstructurenumbercommand\csname\currentheadhash\c!deepnumbercommand\endcsname
- \fi
- \ifconditional\headisdisplay % \ifdisplaysectionhead
- % can be nilled with \setnostrut
- \headparameter\c!numbercommand{\setstrut\begstrut#1\endstrut}%
- \else
- \headparameter\c!numbercommand{#1}%
- \fi
- \endgroup}
-
-% \newif\ifheadnumbercontent
-% \newif\ifemptyhead
-% \newif\ifdisplaysectionhead
+\unexpanded\def\strc_rendering_initialize_style_and_color_inline#1#2%
+ {\dontconvertfont
+ \setfalse\fontattributeisset
+ \useheadstyleandcolor\c!style\c!color\relax
+ \ifconditional\fontattributeisset
+ \updateraggedskips % \setupspacing
+ \fi
+ \setfalse\fontattributeisset
+ \useheadstyleandcolor#1#2\relax
+ \ifconditional\fontattributeisset
+ \updateraggedskips % \setupspacing
+ \fi}
\let\currentstructurereferenceattribute\attributeunsetvalue
@@ -142,42 +112,45 @@
% maybe auto: backreference when given, else list
\fi\fi}
-\unexpanded\def\placecurrentheadtext
- {\beginheadplacement
+% a bit messy ... empty in place instead of self .. might change (or use special
+% whatsig (invisible user one)
+
+\unexpanded\def\strc_rendering_place_head_text
+ {\strc_rendering_start_placement
\setheadmarking
\doresettructureheadnumbercontent
- \ifconditional\headleaveempty
- \setbox\sectionheadbox\hbox \headreferenceattributes to \zeropoint{}%
- \makestrutofbox\sectionheadbox
+ \ifconditional\c_strc_sectioning_empty
+ \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}%
\else
\docheckheadreference
- \setbox\sectionheadbox\hbox \headreferenceattributes
+ \setbox\b_strc_rendering_head\hbox \headreferenceattributes
{\spac_grids_set_local_snapping{\headparameter\c!internalgrid}%
\doresettructureheadnumbercontent
\useheadstyleparameter\c!style
\setinlineheadreferenceattributes
- \headparameter\c!command{}{\doplaceheadtextcomponent\getheadtitle}}%
+ \strc_rendering_inject_text}%
\fi
- \endheadplacement{\getheadsyncs}}
+ \strc_rendering_stop_placement}
-\unexpanded\def\placecurrentheadnumbertext
- {\beginheadplacement
+\unexpanded\def\strc_rendering_place_head_number_and_text
+ {\strc_rendering_start_placement
\setheadmarking
- \doiftextelse{\getheadnumber}\dosettructureheadnumbercontent\doresettructureheadnumbercontent
- \ifconditional\headleaveempty
- \setbox\sectionheadbox\hbox \headreferenceattributes to \zeropoint{}%
- \makestrutofbox\sectionheadbox
+ \doiftextelse\getheadnumber
+ \dosettructureheadnumbercontent
+ \doresettructureheadnumbercontent
+ \ifconditional\c_strc_sectioning_empty
+ \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}%
\else % = needed
\docheckheadreference
- \setbox\sectionheadbox\hbox \headreferenceattributes
+ \setbox\b_strc_rendering_head\hbox \headreferenceattributes
{\spac_grids_set_local_snapping{\headparameter\c!internalgrid}%
\useheadstyleparameter\c!style
\setinlineheadreferenceattributes
- \headparameter\c!command{\doplaceheadnumbercomponent\getheadnumber}{\doplaceheadtextcomponent\getheadtitle}}%
+ \strc_rendering_inject_number_and_text}%
\fi
- \endheadplacement{\getheadsyncs}}
+ \strc_rendering_stop_placement}
-\unexpanded\def\placecurrentheadempty
+\unexpanded\def\strc_rendering_place_head_empty
{\hbox \headreferenceattributes {\getheadsyncs}}
%D \starttyping
@@ -192,54 +165,96 @@
%D \MySubject{feeling stretched feeling stretched feeling stretched feeling stretched}
%D \stoptyping
-\let\headlastlinewidth\!!zeropoint
+% helpers
-\def\localheadheight {\strutht}
-\def\localheaddepth {\strutdp}
-\def\localheadlineheight{\lineheight}
+% \defineinmargin [ChapterInMargin] [outer] [normal] [distance=0.3em]
+%
+% \defineheadplacement[MyTest][horizontal]#1#2%
+% {\startlocalheadsetup
+% %\ChapterInMargin{\headhbox{\strut#2}}% proper destination, ref okay
+% \ChapterInMargin{\strut#2}% zero destination, ref okay
+% \stoplocalheadsetup}
+%
+% \setuphead
+% [chapter]
+% [alternative=MyTest]
+
+\unexpanded\def\headhbox{\hbox\headreferenceattributes}
+\unexpanded\def\headvbox{\vbox\headreferenceattributes}
-\def\dolocalheadsetup % koppeling met standaard kopcommando / engels
- {\forgetall % traag dus ...
- \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}}
+\unexpanded\def\startlocalheadsetup{\bgroup\strc_rendering_initialize_spacing}
+\unexpanded\def\stoplocalheadsetup {\egroup}
-\def\beginheadplacement
+\unexpanded\def\strc_rendering_initialize_spacing
+ {\forgetall % local !
+ \edef\p_align{\headparameter\c!align}%
+ \ifx\p_align\empty \else
+ \setupalign[\p_align]%
+ \fi
+ \edef\p_tolerance{\headparameter\c!tolerance}%
+ \ifx\p_tolerance\empty \else
+ \setuptolerance[\p_tolerance]%
+ \fi
+ \edef\p_strut{\headparameter\c!strut}%
+ \ifx\p_strut\v!no
+ \setnostrut
+ \fi
+ \let\\\strc_rendering_shortcut_backslash}
+
+\unexpanded\def\strc_rendering_shortcut_backslash
+ {\crlf
+ \strut
+ \ignorespaces}
+
+\def\strc_rendering_start_placement
{\bgroup
\setsystemmode\currenthead
- \xdef\localheadheight {\the\strutht}%
- \xdef\localheaddepth {\the\strutdp}%
- \xdef\localheadlineheight{\the\lineheight}%
- % == \globallet\localheaddepth\strutdp
- \everypar\emptytoks % needed indeed
- \noindent % ipv \whitespace elders, na \forgetall !
+ %
+ \strc_rendering_initialize_alternatives
+ \strc_rendering_initialize_dimensions
+ %
+ \strc_rendering_initialize_line_state
+ \reseteverypar % needed indeed
+ \noindent % ipv \whitespace elders, na \forgetall !
\bgroup
- \doifinsetelse{\headparameter\c!aligntitle}{\v!yes,\v!float}% new
- {\skip0 1\leftskip
- \skip2 1\rightskip
- \xdef\localheadskip{\the\skip0}%
- \forgetall
- \leftskip\skip0
- \rightskip\skip2
- \setlocalhsize\hsize\localhsize
- \forgetbothskips}
- {\globallet\localheadskip\!!zeropoint
- \forgetall}%
+ \edef\p_aligntitle{\headparameter\c!aligntitle}%
+ \ifx\p_aligntitle\v!yes
+ \strc_rendering_initialize_hsize_local
+ \else\ifx\p_aligntitle\v!float
+ \strc_rendering_initialize_hsize_local
+ \else
+ \strc_rendering_initialize_hsize_global
+ \fi\fi
\setfalse\inhibitmargindata % brrrr is set in forgetall
\dontcomplain
\postponenotes
- \iflocation
- \ifconditional\headisdisplay % \ifdisplaysectionhead
- \else
- % obsolete: \noninterferingmarks
- \fi
- \fi
- \resetinteractionparameter\c!style
+ \strc_rendering_initialize_interaction
+ % delayed
+ \let\localheadsetup \strc_rendering_initialize_spacing % historic name
+ \let\headsetupspacing\strc_rendering_initialize_spacing}
+
+\def\strc_rendering_initialize_hsize_local
+ {\global\d_strc_rendering_local_leftoffset \leftskip
+ \global\d_strc_rendering_local_rightoffset\rightskip
+ % \forgetall
+ % \leftskip \d_strc_rendering_local_leftoffset % no stretch
+ % \rightskip\d_strc_rendering_local_rightoffset % no stretch
+ % \setlocalhsize
+ % \hsize\localhsize
+ % \forgetbothskips}
+ \scratchwidth\availablehsize
+ \forgetall
+ \hsize\scratchwidth}
+
+\def\strc_rendering_initialize_hsize_global
+ {\global\d_strc_rendering_local_leftoffset \zeropoint
+ \global\d_strc_rendering_local_rightoffset\zeropoint
+ \forgetall}
+
+\def\strc_rendering_initialize_interaction
+ {\resetinteractionparameter\c!style
\resetinteractionparameter\c!color
- \resetinteractionparameter\c!contrastcolor
- %\strictouterreferencestrue % tzt instelling
- \let\localheadsetup\dolocalheadsetup}
+ \resetinteractionparameter\c!contrastcolor}
% \setuphead[chapter] [style=\bfd,after=,hang=line] % fit broad 2
% \setuphead[section] [style=\bfc,after=,hang=line]
@@ -259,87 +274,106 @@
% \subsubsection {Test\\Test} \input tufte \page
% \subsubsubsection{Test\\Test} \input tufte \page
-\def\hangheadplacement
- {\scratchdimen\localheadlineheight
- \bgroup
- \openlineheight\scratchdimen
- \scratchdimen\htdp0%
- \getnoflines\scratchdimen
- \advance\noflines\minusone
- \normalexpanded{\egroup\noflines\the\noflines}% brrr
- \setbox0\hbox{\lower\noflines\scratchdimen\box0}%
- \scratchdimen\dimexpr\htdp0-\localheadheight+\strutdp\relax
- \ht0 \strutht
- \dp0 \strutdp
- \edef\localheaddepth{\the\strutdp}}
-
-\newconditional\continuoussectionhead % oeps, \newif\ifcontinuoushead got lost
-\newbox\sectionheadbox
-
-\def\endheadplacement#1%
- {\noflines\zerocount
- \ifconditional\headisdisplay % \ifdisplaysectionhead
- % new (todo tight == one following line up)
- \processaction
- [\headparameter\c!hang]
- [ \v!line=>\hangheadplacement\noflines\zerocount,
- \v!broad=>\hangheadplacement\getnoflines\scratchdimen,
- \v!fit=>\hangheadplacement\getrawnoflines\scratchdimen,
- \v!none=>\noflines\zerocount,
- \v!default=>\noflines\zerocount,
- \v!unknown=>\hangheadplacement\noflines\numexpr0\commalistelement-1\relax]%
- % so far
- \let\headlastlinewidth\!!zeropoint
+\newdimen\d_strc_rendering_hang_height
+\newcount\n_strc_rendering_hang_lines
+
+\newdimen\d_strc_rendering_local_height
+\newdimen\d_strc_rendering_local_depth
+\newdimen\d_strc_rendering_local_lineheight
+
+\def\strc_rendering_initialize_line_state
+ {\global\d_strc_rendering_local_height\strutht
+ \global\d_strc_rendering_local_depth\strutdp
+ \global\d_strc_rendering_local_lineheight\lineheight}
+
+\def\strc_rendering_check_hang
+ {\begingroup
+ \openlineheight\d_strc_rendering_local_lineheight
+ \d_strc_rendering_hang_height\htdp\b_strc_rendering_head
+ \getnoflines\d_strc_rendering_hang_height
+ \normalexpanded{\endgroup\n_strc_rendering_hang_lines\the\numexpr\noflines-\plusone\relax}% brrr
+ \setbox\b_strc_rendering_head\hbox{\lower\n_strc_rendering_hang_lines\d_strc_rendering_hang_height\box\b_strc_rendering_head}%
+ \d_strc_rendering_hang_height\dimexpr\htdp\b_strc_rendering_head-\d_strc_rendering_local_height+\strutdp\relax
+ \ht\b_strc_rendering_head\strutht
+ \dp\b_strc_rendering_head\strutdp
+ \d_strc_rendering_local_depth\strutdp}
+
+\installcorenamespace{headplacementcheckhang}
+
+\setvalue{\??headplacementcheckhang\v!line }{\strc_rendering_check_hang
+ \n_strc_rendering_hang_lines\zerocount}
+\setvalue{\??headplacementcheckhang\v!broad }{\strc_rendering_check_hang
+ \getnoflines\d_strc_rendering_hang_height}
+\setvalue{\??headplacementcheckhang\v!fit }{\strc_rendering_check_hang
+ \getrawnoflines\d_strc_rendering_hang_height}
+\setvalue{\??headplacementcheckhang\v!none }{\n_strc_rendering_hang_lines\zerocount}
+\setvalue{\??headplacementcheckhang }{\n_strc_rendering_hang_lines\zerocount}
+\setvalue{\??headplacementcheckhang\s!unknown}{\strc_rendering_check_hang
+ \n_strc_rendering_hang_lines\numexpr\p_hang-\plusone\relax}
+
+\def\strc_rendering_initialize_line_hang
+ {\ifconditional\headisdisplay
+ \edef\p_hang{\headparameter\c!hang}%
+ \expandcheckedcsname\??headplacementcheckhang\p_hang\s!unknown
+ \relax
+ \else
+ \n_strc_rendering_hang_lines \zerocount
+ \d_strc_rendering_hang_height\zeropoint
+ \fi}
+
+\def\strc_rendering_stop_placement
+ {\n_strc_rendering_hang_lines\zerocount
+ \ifconditional\headisdisplay
+ \strc_rendering_initialize_line_hang
% kind of special, we want to snap heads also according to local specs local
\ifgridsnapping
\hbox\bgroup % extra hbox will trigger global snapper on top of local
- \edef\currentheadgridsnapping{\headparameter\c!grid}%
+ \edef\p_grid{\headparameter\c!grid}%
\ifconditional\headisdisplay
- \ifx\currentheadgridsnapping\empty\else
+ \ifx\p_grid\empty\else
\useheadstyleandcolor\c!style\c!color
\setupinterlinespace
\useheadstyleandcolor\c!textstyle\c!textcolor
\setupinterlinespace
\fi
\fi
- \snaptogrid[\currentheadgridsnapping]\hbox
- {\hskip\localheadskip\hskip\headparameter\c!margin\box\sectionheadbox}%
+ \snaptogrid[\p_grid]\hbox
+ {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax\box\b_strc_rendering_head}%
\egroup
\else
\hbox
- {\hskip\localheadskip\hskip\headparameter\c!margin\box\sectionheadbox}%
+ {\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax\box\b_strc_rendering_head}%
\fi
\flushnotes % new, not really needed
\endgraf
\ifvmode
- \ifnum\noflines>\zerocount
- \dorecurse\noflines{\nointerlineskip\dosomebreak\nobreak\strut\endgraf}% to be checked
+ \ifnum\n_strc_rendering_hang_lines>\zerocount
+ \dorecurse\n_strc_rendering_hang_lines{\nointerlineskip\dosomebreak\nobreak\strut\endgraf}% to be checked
\fi
\nointerlineskip
\dosomebreak\nobreak
\fi
- #1%
+ \getheadsyncs
\else
\strut
\flushnotes % new, here since we're in par mode
- \unhbox\sectionheadbox
- \globallet\headlastlinewidth\!!zeropoint
- #1%
- \hskip\numberheaddistance\!!plus\numberheaddistance\!!minus.25\dimexpr\numberheaddistance\relax
- \hskip\continuousheadsignal\ignorespaces
+ \unhbox\b_strc_rendering_head
+ \getheadsyncs
+ \hskip\headnumberdistance\s!plus\headnumberdistance\s!minus.25\dimexpr\headnumberdistance\relax
+ \strc_sectioning_inject_continuous_signal
\fi
- \ifconditional\headisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay
\ifvmode
\ifgridsnapping % important, font related depth, see comment
\prevdepth\strutdp
\else
- \prevdepth\localheaddepth
+ \prevdepth\d_strc_rendering_local_depth
\fi
\fi
\fi
\egroup
\egroup
- \ifconditional\headisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay
\useindentnextparameter\headparameter
\else
\nonoindentation % recently added, was a bug
@@ -359,56 +393,168 @@
% \input tufte \par
% \stopnarrower
-\installcorenamespace{headplacementalternative}
-\installcorenamespace{headplacementnature}
-
-\let\numberheadalternative\v!normal
-
-\unexpanded\def\defineheadplacement
- {\dodoubleargument\dodefineheadplacement}
-
-% \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}
+% \startsetups[\??headrenderings:\v!vertical:\v!sectiona]
+% ... there will be a more public namespace
+% \stopsetups
+
+\installcorenamespace{headplacementalternative}
+\installcorenamespace{headrenderings}
+\installcorenamespace{headalternative}
-\def\dodefineheadplacementnop[#1][#2]%
- {\setvalue{\??headplacementnature#1}{#2}%
- \setvalue{\??headplacementalternative#1}}
+\installcommandhandler \??headalternative {headalternative} \??headalternative % or just \??head
-\def\dodefineheadplacement[#1][#2]%
+\setupheadalternative
+ [%\c!width=\headparameter\c!width,
+ %\c!distance=\headparameter\c!distance,
+ \c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\currentheadalternative]
+
+\let\currentheadalternative \v!normal
+\let\currentheadrenderingsetup \empty
+\let\currentheadrenderingalternative\v!vertical
+
+\unexpanded\def\defineheadplacement % old mechanism
+ {\dodoubleargument\strc_rendering_define_placement}
+
+\def\strc_rendering_define_placement[#1][#2]%
{\doifnextbgroupelse
- {\dodefineheadplacementyes[#1][#2]}%
- {\dodefineheadplacementnop[#1][#2]}}
+ {\strc_rendering_define_placement_yes[#1][#2]}%
+ {\strc_rendering_define_placement_nop[#1][#2]}}
+
+\def\strc_rendering_define_placement_yes[#1][#2]%
+ {\defineheadalternative[#1][\c!alternative=#2,\c!renderingsetup=\??headrenderings:\v!command]%
+ \setuvalue{\??headplacementalternative#1}##1##2}
+
+\def\strc_rendering_define_placement_nop[#1][#2]%
+ {\defineheadalternative[#1][\c!alternative=#2,\c!renderingsetup=\??headrenderings:\v!command]%
+ \setuvalue{\??headplacementalternative#1}}
+
+% these can be used in setups:
+%
+% \headnumbercontent
+% \headtextcontent
+%
+% \headwidth
+% \headtextwidth
+% \headnumberdistance
+% \headnumberwidth
+% \headsetupspacing
+%
+% \headshownumber
+% \headisdisplay
+
+\let\headnumbercontent\empty
+\let\headtextcontent \empty
+
+\newdimen\headwidth
+\newdimen\headtextwidth
+\newdimen\headnumberdistance
+\newdimen\headnumberwidth
+
+% \newconditional\headshownumber % defined already
+% \newconditional\headisdisplay % defined already
+
+\unexpanded\def\strc_rendering_initialize_alternatives
+ {\edef\currentheadalternative {\headparameter \c!alternative}%
+ \edef\currentheadrenderingsetup {\headalternativeparameter\c!renderingsetup}%
+ \edef\currentheadrenderingalternative{\headalternativeparameter\c!alternative}%
+ \ifx\currentheadrenderingalternative\empty
+ \let\currentheadrenderingalternative\v!vertical
+ \fi
+ \ifx\currentheadrenderingalternative\v!horizontal
+ \global\setfalse\headisdisplay % global
+ \else
+ \global\settrue\headisdisplay % global
+ \fi}
-\def\presetnumberheadalternative
- {\doifelsevalue{\??headplacementnature\numberheadalternative}\v!horizontal\setfalse\settrue\headisdisplay}
+\unexpanded\def\strc_rendering_initialize_dimensions
+ {\headwidth \headparameter\c!width \relax % \zeropoint == unset
+ \headnumberwidth \headparameter\c!numberwidth\relax % \zeropoint == unset
+ \headnumberdistance\headparameter\c!distance \relax
+ \headtextwidth \headparameter\c!textwidth \relax} % \zeropoint == unset
-\def\normalplacehead
- {\csname\??headplacementalternative\ifcsname\??headplacementalternative\numberheadalternative\endcsname\numberheadalternative\else\v!normal\fi\endcsname}
+\unexpanded\def\headtextcontent
+ {\begingroup
+ \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor
+ \headparameter\c!commandbefore\relax
+ \ifcsname\currentheadhash\c!deeptextcommand\endcsname
+ \expandafter\let\expandafter\deepstructuretitlecommand\csname\currentheadhash\c!deeptextcommand\endcsname
+ \fi
+ \ifconditional\headisdisplay
+ % struts can be nilled with \setnostrut
+ \headparameter\c!textcommand{\setstrut\begstrut\getheadtitle\endstrut}%
+ \global\d_strc_rendering_local_height\strutht
+ \global\d_strc_rendering_local_depth\strutdp
+ \global\d_strc_rendering_local_lineheight\lineheight
+ \headparameter\c!commandafter\relax
+ \endgraf
+ \else
+ \headparameter\c!textcommand{\getheadtitle}%
+ \headparameter\c!commandafter\relax
+ \fi
+ \endgroup}
+
+\unexpanded\def\headnumbercontent
+ {\begingroup
+ \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor
+ \ifcsname\currentheadhash\c!deepnumbercommand\endcsname
+ \expandafter\let\expandafter\deepstructurenumbercommand\csname\currentheadhash\c!deepnumbercommand\endcsname
+ \fi
+ \ifconditional\headisdisplay
+ % can be nilled with \setnostrut
+ \headparameter\c!numbercommand{\setstrut\begstrut\getheadnumber\endstrut}%
+ \else
+ \headparameter\c!numbercommand{\getheadnumber}%
+ \fi
+ \endgroup}
+
+\unexpanded\def\strc_rendering_inject_number_and_text
+ {\edef\p_command{\headparameter\c!command}% assumes \unexpanded definition
+ \ifx\p_command\empty
+ \directsetup\currentheadrenderingsetup
+ \else
+ \p_command\headnumbercontent\headtextcontent
+ \fi}
+
+\unexpanded\def\strc_rendering_inject_text
+ {\edef\p_command{\headparameter\c!command}% assumes \unexpanded definition
+ \ifx\p_command\empty
+ \directsetup\currentheadrenderingsetup
+ \else
+ \p_command\empty\headtextcontent
+ \fi}
-\def\setheaddisplay % used in strc-sec
- {\doifelsevalue{\??headplacementnature\headparameter\c!alternative}\v!horizontal
- {\setfalse\headisdisplay}
- {\settrue \headisdisplay}}
+\startsetups[\??headrenderings:\v!command]
+ \csname\??headplacementalternative\currentheadalternative\endcsname \headnumbercontent \headtextcontent
+\stopsetups
-\defineheadplacement[\v!paragraph][\v!vertical]#1#2%
- {\vbox
- {\localheadsetup
- \begstrut
- \ifconditional\headshownumber % \ifheadnumbercontent
- #1\hskip\numberheaddistance
- \fi
- #2}}
+% obsolete
+%
+% \def\normalplacehead % hooks into \c!command
+% {\csname\??headplacementalternative\ifcsname\??headplacementalternative\currentheadalternative\endcsname\currentheadalternative\else\v!normal\fi\endcsname}
+
+\defineheadalternative
+ [\v!paragraph]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!paragraph]
+
+\startsetups[\??headrenderings:\v!paragraph]
+ \vbox {
+ \headsetupspacing
+ \begstrut
+ \ifconditional\headshownumber % \ifheadnumbercontent
+ \headnumbercontent
+ \hskip\headnumberdistance
+ \fi
+ \headtextcontent
+ }
+\stopsetups
% \setuphead
% [chapter]
@@ -417,129 +563,183 @@
% \chapter{Oeps oeps oeps} \input tufte \section{Oeps}
% \chapter{Oeps oeps oeps} \section{Oeps} \input tufte
-\defineheadplacement[\v!normal][\v!vertical]#1#2%
- {\vbox
- {\localheadsetup
- \edef\headwidth {\headparameter\c!width }%
- \edef\headnumberwidth{\headparameter\c!numberwidth}%
- \edef\headtextwidth {\headparameter\c!textwidth }%
- \ifconditional\headshownumber
- \ifx\headwidth\empty
- \else
- \ifx\headnumberwidth\empty
- \ifx\headtextwidth\empty\else
- \edef\headnumberwidth{\the\dimexpr\headwidth-\headtextwidth\relax}%
+\defineheadalternative
+ [\v!normal]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!normal]
+
+\startsetups[\??headrenderings:\v!normal]
+ \vbox {
+ \headsetupspacing
+ \ifconditional\headshownumber
+ \ifdim\headwidth=\zeropoint \else
+ \ifdim\headnumberwidth=\zeropoint
+ \ifdim\headtextwidth=\zeropoint \else
+ \headnumberwidth\dimexpr\headwidth-\headtextwidth\relax
+ \fi
+ \else
+ \ifdim\headtextwidth=\zeropoint
+ \headtextwidth\dimexpr\headwidth-\headnumberwidth\relax
+ \fi
+ \fi
+ \hsize\headwidth
\fi
- \else
- \ifx\headtextwidth\empty
- \edef\headtextwidth{\the\dimexpr\headwidth-\headnumberwidth\relax}%
+ \ifdim\headnumberwidth=\zeropoint\else
+ \headnumberdistance\zeropoint
\fi
- \fi
- \hsize\headwidth
- \fi
- \ifx\headnumberwidth\empty\else
- \let\numberheaddistance\!!zeropoint
+ \setbox\scratchbox\hbox \ifdim\headnumberwidth=\zeropoint\else to \headnumberwidth\fi{\headnumbercontent}
+ \scratchdimen\dimexpr\wd\scratchbox+\headnumberdistance\relax
+ \ifdim\headtextwidth=\zeropoint\else
+ \hsize\dimexpr\scratchdimen+\headtextwidth\relax
+ \fi
+ \hangindent\scratchdimen
+ \hangafter \plusone
+ \noindent
+ \box\scratchbox
+ \hskip\headnumberdistance
+ \else
+ \ifdim\headtextwidth=\zeropoint
+ \ifdim\headwidth=\zeropoint \else
+ \hsize\headwidth
+ \fi
+ \else
+ \hsize\headtextwidth
+ \fi
+ \noindent
\fi
- \setbox\scratchbox\hbox \ifx\headnumberwidth\empty\else to \headnumberwidth\fi{{#1}}%
- \scratchdimen\dimexpr\wd\scratchbox+\numberheaddistance\relax
- \ifx\headtextwidth\empty\else
- \hsize\dimexpr\scratchdimen+\headparameter\c!textwidth\relax
+ \headtextcontent
+ }
+\stopsetups
+
+\defineheadalternative
+ [\v!inmargin]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!inmargin]
+
+\startsetups[\??headrenderings:\v!inmargin]
+ \vbox {
+ \headsetupspacing
+ \begstrut % use one \strut here!
+ \dontleavehmode % in case there is no strut, else side effects with llap
+ \ifconditional\headshownumber
+ \llap {
+ \hbox {
+ \hfill
+ \headnumbercontent
+ \hskip\dimexpr\d_strc_rendering_local_leftoffset+\doifoddpageelse\leftmargindistance\rightmargindistance\relax
+ }
+ }
\fi
- \hangindent\scratchdimen
- \hangafter \plusone
- \noindent
- \box\scratchbox\hskip\numberheaddistance
- \else
- \ifx\headtextwidth\empty
- \ifx\headwidth\empty
- \else
- \hsize\headwidth
- \fi
- \else
- \hsize\headtextwidth
+ \headtextcontent
+ }
+\stopsetups
+
+\defineheadalternative
+ [\v!margin]
+ [\v!inmargin]
+
+% \startsetups[\??headrenderings:\v!vertical:\v!margin]
+% \directsetup{\??headrenderings:\v!vertical:\v!inmargin}
+% \stopsetups
+
+\defineheadalternative
+ [\v!middle]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!middle]
+
+\startsetups[\??headrenderings:\v!middle]
+ \vbox {
+ \headsetupspacing
+ \veryraggedcenter
+ \let\\\endgraf
+ \let\crlf\endgraf
+ \ifconditional\headshownumber
+ \strut
+ \headnumbercontent
+ \par
\fi
- \noindent
- \fi
- #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\headshownumber
-% \llap{\hbox{\hfill{#1}\hskip\localheadskip\hskip\leftmargindistance}}% introduces whitespace
-% % maybe better:
-% % \inleftmargin{\hbox{\hss{#1}\hskip\localheadskip}}%
-% \fi
-% {#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\headshownumber
- \llap{\hbox{\hfill{#1}\hskip\dimexpr\localheadskip+\doifoddpageelse\leftmargindistance\rightmargindistance\relax}}% introduces whitespace
- \fi
- {#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
- {\localheadsetup
- \veryraggedcenter
- \let\\\endgraf
- \let\crlf\endgraf
- \ifconditional\headshownumber
- \strut#1\par
- \fi
- \begstrut#2}}
-
-\defineheadplacement[\v!text][\v!horizontal]#1#2%
- {\bgroup
- \localheadsetup % no stretch in distance
- \ifconditional\headshownumber
- {#1}\kern\numberheaddistance
- \fi
- {\begstrut#2}%
- \egroup}
-
-\unexpanded\def\placeheadlohialternative#1#2#3%
- {\ifconditional\headshownumber
- \setbox0\hbox{#2}
- \setbox2=#1{\localheadsetup\advance\hsize-\wd0\relax#3}%
- \hbox{\box0\hskip\numberheaddistance\box2}%
- \else
- #1{\localheadsetup\noindent#3}%
- \fi}
-
-% onder/boven lijnt het nummer op de onderste/bovenste regel
-% uit van een meerregelige kop
-
-\defineheadplacement[\v!bottom][\v!vertical]#1#2{\placeheadlohialternative\vbox{#1}{#2}}
-\defineheadplacement[\v!top] [\v!vertical]#1#2{\placeheadlohialternative\vtop{#1}{#2}}
-
-% helpers
-
-% \defineinmargin [ChapterInMargin] [outer] [normal] [distance=0.3em]
-%
-% \defineheadplacement[MyTest][horizontal]#1#2%
-% {\startlocalheadsetup
-% %\ChapterInMargin{\headhbox{\strut#2}}% proper destination, ref okay
-% \ChapterInMargin{\strut#2}% zero destination, ref okay
-% \stoplocalheadsetup}
-%
-% \setuphead
-% [chapter]
-% [alternative=MyTest]
-
-\unexpanded\def\headhbox{\hbox\headreferenceattributes}
-\unexpanded\def\headvbox{\vbox\headreferenceattributes}
-
-\unexpanded\def\startlocalheadsetup{\bgroup\localheadsetup}
-\unexpanded\def\stoplocalheadsetup {\egroup}
+ \begstrut
+ \headtextcontent
+ \endstrut
+ }
+\stopsetups
+
+\defineheadalternative
+ [\v!text]
+ [\c!alternative=\v!horizontal,
+ \c!renderingsetup=\??headrenderings:\v!text]
+
+\startsetups[\??headrenderings:\v!text]
+ \begingroup
+ \headsetupspacing % no stretch in distance
+ \ifconditional\headshownumber
+ \headnumbercontent
+ \kern\headnumberdistance
+ \fi
+ \begstrut
+ \headtextcontent
+ \endstrut
+ \endgroup
+\stopsetups
+
+% onder/boven lijnt het nummer op de onderste/bovenste regel uit van een meerregelige kop
+
+\defineheadalternative
+ [\v!bottom]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!bottom]
+
+\startsetups[\??headrenderings:\v!bottom]
+ \ifconditional\headshownumber
+ \setbox0\hbox {
+ \headnumbercontent
+ }
+ \setbox2\vbox {
+ \headsetupspacing
+ \advance\hsize-\wd0\relax
+ \headtextcontent
+ }
+ \hbox {
+ \box0
+ \hskip\headnumberdistance
+ \box2
+ }
+ \else
+ \vbox {
+ \headsetupspacing
+ \noindent
+ \headtextcontent
+ }
+ \fi
+\stopsetups
+
+\defineheadalternative
+ [\v!top]
+ [\c!alternative=\v!vertical,
+ \c!renderingsetup=\??headrenderings:\v!top]
+
+\startsetups[\??headrenderings:\v!top]
+ \ifconditional\headshownumber
+ \setbox0\hbox {
+ \headnumbercontent
+ }
+ \setbox2\vtop {
+ \headsetupspacing
+ \advance\hsize-\wd0\relax
+ \headtextcontent
+ }
+ \hbox {
+ \box0
+ \hskip\headnumberdistance
+ \box2
+ }
+ \else
+ \vtop{
+ \headsetupspacing
+ \noindent
+ \headtextcontent
+ }
+ \fi
+\stopsetups
\protect \endinput
diff --git a/tex/context/base/strc-sbe.mkiv b/tex/context/base/strc-sbe.mkiv
index a98b67885..4ea08b30c 100644
--- a/tex/context/base/strc-sbe.mkiv
+++ b/tex/context/base/strc-sbe.mkiv
@@ -27,78 +27,76 @@
% \chapter{second} \section{alpha} test \section{beta} test \page
% \stopbodymatter % optional
-\unexpanded\def\definesectionblock{\dotripleargument\dodefinesectionblock}
-\unexpanded\def\setupsectionblock {\dodoubleargument\dosetupsectionblock}
-\def\setsectionblock {\dosingleargument\dosetsectionblock}
-
-\def\sectionblockparameter#1%
- {\csname
- \ifcsname\??sb\currentsectionblock#1\endcsname\??sb\currentsectionblock#1\else\s!empty\fi
- \endcsname}
-
-\newtoks \everybeforesectionblock
-\newtoks \everyaftersectionblock
-
-\def\dodefinesectionblock[#1][#2][#3]% singular plural settings
- {\getparameters
- [\??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
- \setsectionblockenvironment{#1}\empty
- \setvalue {\e!start#2}{\startsectionblock[#1]}%
- \setvalue {\e!stop #2}{\stopsectionblock}}
+\installcorenamespace{sectionblock}
+
+\installcommandhandler \??sectionblock {sectionblock} \??sectionblock
+
+\setupsectionblock
+ [\c!number=\v!yes,
+ \c!page=\v!right] % otherwise marks are reset too soon
+
+\newtoks\everybeforesectionblock
+\newtoks\everyaftersectionblock
+
+\let\strc_sectionblock_define_normal\definesectionblock
+
+\unexpanded\def\definesectionblock
+ {\dotripleargument\strc_sectionblock_define}
+
+\def\strc_sectionblock_define[#1][#2][#3]% singular plural settings
+ {\strc_sectionblock_define_normal[#1][#3]%
+ \expandafter\newif\csname if#2\endcsname % obsolete
+ \strc_sectionblock_set_environment{#1}\empty
+ \setuvalue{\e!start#2}{\startsectionblock[#1]}%
+ \setuvalue{\e!stop #2}{\stopsectionblock}}
\ifdefined \resetallstructuremarks \else
\let\resetallstructuremarks\relax
\fi
+\def\strc_sectionblock_handle_page
+ {\edef\p_strc_sectionblock_page{\sectionblockparameter\c!page}%
+ \ifx\p_strc_sectionblock_page\empty \else
+ \page[\p_strc_sectionblock_page]%
+ \fi}
+
\appendtoks
- \doifsomething{\sectionblockparameter\c!page}{\page[\sectionblockparameter\c!page]}%
+ \strc_sectionblock_handle_page
\resetallstructuremarks
- \getsectionblockenvironment\currentsectionblock
+ \strc_sectionblock_get_environment\currentsectionblock
\sectionblockparameter\c!before % don't move
\dostarttagged\t!division\currentsectionblock
\to \everybeforesectionblock
\appendtoks
\sectionblockparameter\c!after % don't move
- \doifsomething{\sectionblockparameter\c!page}{\page[\sectionblockparameter\c!page]}%
+ \strc_sectionblock_handle_page
\dostoptagged
\resetallstructuremarks
\to \everyaftersectionblock
-\def\dosetupsectionblock[#1]%
- {\getparameters[\??sb#1]}% [#2]
+\unexpanded\def\setsectionblock
+ {\dosingleargument\strc_sectionblock_set}
-\def\dosetsectionblock[#1]% used to set the default
- {\edef\currentsectionblock{\ctxlua{structures.sections.setblock("#1")}}}
+\def\strc_sectionblock_set[#1]% used to set the default
+ {\edef\currentsectionblock{\ctxcommand{setsectionblock("#1")}}}
\let\currentsectionblock\empty % was \s!unknown
\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\currentsectionblock{\ctxlua{structures.sections.pushblock("#1")}}%
- \csname #1true\endcsname % for old times sake
+ \edef\currentsectionblock{\ctxcommand{pushsectionblock("#1")}}%
+ \csname #1true\endcsname % obsolete
\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\setsectionblockenvironment#1#2%
- {\long\setvalue{\??sb\s!do#1}{\do{#2}}}
-
-\def\getsectionblockenvironment#1%
- {\let\do\firstofoneargument
- %\sectionblockparameter{\s!do#1}}
- \csname\??sb\s!do#1\endcsname}
+ {\showmessage\m!structures2\currentsectionblock
+ \the\everyaftersectionblock\relax
+ \edef\currentsectionblock{\ctxcommand{popsectionblock()}}%
+ \endgroup}
%D \starttyping
%D \startsectionblockenvironment[frontpart]
@@ -120,10 +118,20 @@
%D \stoptext
%D \stoptyping
-\setvalue{\e!start\v!sectionblockenvironment}%
- {\dosingleargument\dostartsectionblockenvironment}
+\installcorenamespace{sectionblockenvironment}
+
+\unexpanded\def\strc_sectionblock_set_environment#1#2%
+ {\setvalue{\??sectionblockenvironment#1}{#2}}
+
+\unexpanded\def\strc_sectionblock_get_environment#1%
+ {\csname\??sectionblockenvironment#1\endcsname}
+
+\unexpanded\setvalue{\e!start\v!sectionblockenvironment}%
+ {\dosingleargument\strc_sectionblock_environment_start}
+
+\letvalue{\e!stop\v!sectionblockenvironment}\relax
-\def\dostartsectionblockenvironment[#1]% evt \pushendofline \popendofline
- {\grabuntil{\e!stop\v!sectionblockenvironment}{\setsectionblockenvironment{#1}}}
+\def\strc_sectionblock_environment_start[#1]% evt \pushendofline \popendofline
+ {\grabuntil{\e!stop\v!sectionblockenvironment}{\strc_sectionblock_set_environment{#1}}}
\protect \endinput
diff --git a/tex/context/base/strc-sec.mkiv b/tex/context/base/strc-sec.mkiv
index e9b613f21..826de59bf 100644
--- a/tex/context/base/strc-sec.mkiv
+++ b/tex/context/base/strc-sec.mkiv
@@ -15,7 +15,227 @@
\unprotect
-\ifdefined \v!block \else \def\v!block{block} \fi
+\installcorenamespace{structure}
+
+\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters
+
+\setupstructure % not a user command so we might need to change the name
+ [\c!number=,
+ \c!level=,
+ \c!name=,
+ \c!title=,
+ \c!bookmark=,
+ \c!marking=,
+ \c!list=,
+ \c!label=,
+ \c!coupling=,
+ \c!ownnumber=,
+ \c!sectionseparatorset=\s!default,
+ \c!sectionconversionset=\s!default,
+ \c!sectionstopper=,
+ \c!sectionstarter=,
+ \c!sectionsegments=,
+ \c!sectionresetset=,
+ \c!reference=,
+ \c!backreference=,
+ \c!expansion=\v!no,
+ \c!xmlsetup=,
+ \s!catcodes=,
+ \c!saveinlist=\v!yes]
+
+% maybe flags for list, bm, mark
+
+\def\m_strc_references_prefix_yes{+}
+\def\m_strc_references_prefix_nop{-}
+
+\def\strc_sectioning_set_reference_prefix
+ {\ifx\currentstructurereferenceprefix\empty
+ % nothing
+ \else\ifx\currentstructurereferenceprefix\m_strc_references_prefix_yes
+ \global\advance\prefixcounter \plusone % temp here
+ \setupglobalreferenceprefix[\the\prefixcounter]%
+ \else\ifx\currentstructurereferenceprefix\m_strc_references_prefix_nop
+ \setupglobalreferenceprefix[]%
+ \else
+ \setupglobalreferenceprefix[\currentstructurereferenceprefix]%
+ \fi\fi\fi
+ \let\currentstructurereferenceprefix\referenceprefix}
+
+% why xdef ?
+
+\setupstructure
+ [\c!label={\headparameter{\currentsectionblock\c!label}},
+ \c!incrementnumber=\ifconditional\c_strc_sectioning_increment\v!yes\else\v!no\fi, % not that needed
+ \c!saveinlist=\ifconditional\c_strc_sectioning_to_list\v!yes\else\v!no\fi,
+ \c!level=\currentheadlevel,
+ \c!number=\ifconditional\c_strc_sectioning_increment\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi,
+ \c!expansion=\headparameter\c!expansion,
+ \c!xmlsetup=\headparameter\c!xmlsetup,
+ \s!catcodes=\headparameter\s!catcodes,
+ \c!sectionresetset=\headparameter\c!sectionresetset,
+ \c!sectionseparatorset=\headparameter\c!sectionseparatorset,
+ \c!sectionconversionset=\headparameter\c!sectionconversionset,
+ \c!sectionconversion=\headparameter\c!conversion, % just for compatibility
+ \c!sectionstarter=\headparameter\c!sectionstarter,
+ \c!sectionstopper=\headparameter\c!sectionstopper,
+ \c!sectionset=\headparameter\c!sectionset,
+ \c!sectionsegments=\headparameter\c!sectionsegments,
+ \c!reference=\headparameter\c!reference,
+ \c!referenceprefix=\headparameter\c!referenceprefix]
+
+\unexpanded\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported)
+ {\begingroup
+ \setupstructure[\c!name={#1},#2]%
+ \xdef\currentstructurename {\structureparameter\c!name}%
+ \xdef\currentstructurecoupling {\structureparameter\c!coupling}%
+ \xdef\currentstructureownnumber {\structureparameter\c!ownnumber}% optional own number
+ \xdef\currentstructurelevel {\structureparameter\c!level}%
+ \edef\currentstructureexpansion {\structureparameter\c!expansion}%
+ \xdef\currentstructurexmlsetup {\structureparameter\c!xmlsetup}%
+ \xdef\currentstructurecatcodes {\structureparameter\s!catcodes}%
+ \xdef\currentstructurelabel {\structureparameter\c!label}%
+ \xdef\currentstructurereference {\structureparameter\c!reference}%
+ \xdef\currentstructurereferenceprefix{\structureparameter\c!referenceprefix}%
+ \xdef\currentstructurebackreference {\structureparameter\c!backreference}%
+ \xdef\currentstructureshownumber {\structureparameter\c!number}%
+ \xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}%
+ \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}%
+ \ifx\currentstructureexpansion\s!xml
+ \xmlstartraw
+ \xdef\currentstructuretitle {\structureparameter\c!title}%
+ \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\structureparameter\c!marking}%
+ \xdef\currentstructurelist {\structureparameter\c!list}%
+ \xmlstopraw
+ \ifx\currentstructurelist\empty
+ \globallet\currentstructurelist\currentstructuretitle
+ \fi
+ \globallet\currentstructurecoding\s!xml
+ \else
+ \ifx\currentstructureexpansion\v!yes
+ \xdef\currentstructuretitle {\structureparameter\c!title}%
+ \xdef\currentstructurebookmark{\structureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\structureparameter\c!marking}%
+ \xdef\currentstructurelist {\structureparameter\c!list}%
+ \else
+ \xdef\currentstructuretitle {\detokenizedstructureparameter\c!title}%
+ \xdef\currentstructurebookmark{\detokenizedstructureparameter\c!bookmark}%
+ \xdef\currentstructuremarking {\detokenizedstructureparameter\c!marking}%
+ \xdef\currentstructurelist {\detokenizedstructureparameter\c!list}%
+ \iflocation \ifx\currentstructurebookmark\empty
+ \begingroup
+ \simplifycommands
+ \xdef\currentstructurebookmark{\detokenize\expandafter{\normalexpanded{\structureparameter\c!title}}}%
+ \endgroup
+ \fi \fi
+ \fi
+ \ifx\currentstructurelist\empty
+ \globallet\currentstructurelist\currentstructuretitle
+ \fi
+ \globallet\currentstructurecoding\s!tex
+ \fi
+ \setnextinternalreference
+ \strc_sectioning_set_reference_prefix
+ \xdef\currentstructurenumber{\ctxlua{ % todo: combine with next call, adapt marks accordingly
+ structures.sections.somelevel {
+ references = {
+ internal = \nextinternalreference,
+ block = "\currentsectionblock",
+ reference = "\currentstructurereference",
+ referenceprefix = "\currentstructurereferenceprefix",
+ backreference = "\currentstructurebackreference",
+ },
+ directives = {
+ resetset = "\structureparameter\c!sectionresetset",
+ },
+ metadata = {
+ kind = "section",
+ name = "\currentstructurename",
+ catcodes = \the\ifx\currentstructurecatcodes\empty\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi,
+ coding = "\currentstructurecoding",
+ \ifx\currentstructurecoding\s!xml
+ xmlroot = "\xmldocument",
+ \fi
+ \ifx\currentstructurexmlsetup\empty \else
+ xmlsetup = "\currentstructurexmlsetup",
+ \fi
+ \ifx\currentstructuresaveinlist\v!no
+ nolist = true,
+ \fi
+ \ifx\currentstructureincrementnumber\v!yes
+ increment = "\currentstructureincrementnumber",
+ \fi
+ },
+ titledata = { % we can add mark and reference
+ label = \!!bs\detokenize\expandafter{\currentstructurelabel }\!!es,
+ title = \!!bs\detokenize\expandafter{\currentstructuretitle }\!!es,
+ \ifx\currentstructurebookmark\currentstructuretitle \else
+ bookmark = \!!bs\detokenize\expandafter{\currentstructurebookmark }\!!es,
+ \fi
+ \ifx\currentstructuremarking\currentstructuretitle \else
+ marking = \!!bs\detokenize\expandafter{\currentstructuremarking }\!!es,
+ \fi
+ \ifx\currentstructuresaveinlist\v!no \else
+ \ifx\currentstructurelist\currentstructuretitle \else
+ list = \!!bs\detokenize\expandafter{\currentstructurelist}\!!es,
+ \fi
+ \fi
+ },
+ numberdata = {
+ % needed ?
+ block = "\currentsectionblock",
+ hidenumber = \ifx\currentstructureshownumber\v!no true\else nil\fi, % titles
+ % so far
+ separatorset = "\structureparameter\c!sectionseparatorset",
+ conversion = "\structureparameter\c!sectionconversion", % for good old times sake
+ conversionset = "\structureparameter\c!sectionconversionset",
+ starter = \!!bs\structureparameter\c!sectionstarter\!!es,
+ stopper = \!!bs\structureparameter\c!sectionstopper\!!es,
+ set = "\structureparameter\c!sectionset",
+ segments = "\structureparameter\c!sectionsegments",
+ ownnumber = "\currentstructureownnumber",
+ },
+ userdata = \!!bs\detokenize{#3}\!!es % will be converted to table at the lua end
+ }
+ }}%
+ \xdef\currentstructurelistnumber{\ctxcommand{addtolist(structures.sections.current())}}%
+ % \currentstructuresynchronize has to be called someplace, since it introduces a node
+ \setstructuresynchronization\currentstructurelistnumber
+ \endgroup}
+
+\let\currentstructurenumber \!!zerocount
+\let\currentsectioncountervalue \!!zerocount % redefined later
+\let\previoussectioncountervalue\!!zerocount % redefined later
+
+% We can access the (stored) data with the following macros.
+%
+% \def\MyHeadCommand #1#2{\framed{#1}\framed{#2 / \structureuservariable{subtitle}}}
+% \def\MyListCommand#1#2#3{\externalfigure[\structurelistuservariable{figure}][height=5mm]#2}
+%
+% \setuphead[chapter][command=\MyHeadCommand]
+% \setuplist[chapter][alternative=command,command=\MyListCommand]
+%
+% \starttext
+% \setupheadertexts[chapter]
+% \setupinteraction[state=start]
+% \placebookmarks[chapter]
+% \placelist[chapter]
+% \startchapter[ownnumber=10,title=Ton,list=Hans,marking=Kees,bookmark=Bram][figure=cow.pdf,subtitle=oeps]
+% \stopchapter
+% \stoptext
+
+% todo: #1 => "#1" ... adapt lua code for name and number
+
+\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")}}
% compatibility issue:
%
@@ -43,6 +263,8 @@
% lua interface / names and interface might change
+\newconditional\c_strc_rendering_continuous % not used (mkii ?)
+
\def\setstructurelevel #1#2{\ctxlua{structures.sections.setlevel("#1","#2")}} % name, level|parent
\def\getstructurelevel #1{\ctxlua{structures.sections.getcurrentlevel("#1")}}% name
\def\setstructurenumber #1#2{\ctxlua{structures.sections.setnumber(#1,"#2")}} % level, number (+/-)
@@ -74,6 +296,62 @@
\installcommandhandler \??head {head} \??head
+\setuphead [%
+ %\c!after=,
+ %\c!align=,
+ %\c!aligntitle=,
+ \c!alternative=\v!normal,
+ %\c!before=,
+ %\c!color=,
+ %\c!command=,
+ \c!continue=\v!yes,
+ %\c!coupling=,
+ %\c!deepnumbercommand=,
+ %\c!deeptextcommand=,
+ %\c!default=,
+ \c!distance=\zeropoint,
+ \c!textwidth=\zeropoint, % signal too
+ \c!numberwidth=\zeropoint, % signal too
+ \c!width=\zeropoint, % signal too
+ \c!expansion=\v!no,
+ %\c!file=,
+ %\c!footer=,
+ %\c!grid=,
+ \c!hang=\v!none,
+ %\c!header=,
+ \c!incrementnumber=\v!yes,
+ \c!indentnext=\v!no,
+ %\c!label=,
+ %\c!limittext=\languageparameter\c!limittext,
+ \c!margin=\zeropoint,
+ %\c!margintext=,
+ \c!number=\v!yes,
+ \c!numbercolor=\headparameter\c!color,
+ \c!textcolor=\headparameter\c!color,
+ \c!numberstyle=\headparameter\c!style,
+ \c!textstyle=\headparameter\c!style,
+ %\c!numbercommand=,
+ %\c!textcommand=,
+ \c!ownnumber=\v!no,
+ %\c!page=,
+ \c!placehead=\v!yes,
+ \c!sectionconversionset=\s!default,
+ \c!sectionnumber=\v!yes,
+ %\c!sectionsegments=,
+ \c!sectionseparatorset=\s!default,
+ \c!sectionset=\v!all,
+ \c!interlinespace=,
+ %\c!sectionstopper=,
+ %\c!sectionstarter=,
+ %\c!strut=,
+ %\c!style=,
+ %\c!text=,
+ %\c!tolerance=,
+ %\c!beforesection=\directsetup{document:\currenthead:start}, % these might become defaults i.e. acpect document: namespace
+ %\c!insidesection=\directsetup{document:\currenthead:inside}, % these might become defaults i.e. acpect document: namespace
+ %\c!aftersection=\directsetup{document:\currenthead:stop}, % these might become defaults i.e. acpect document: namespace
+ ]
+
\let\setupheads\setuphead % will go
\appendtoks
@@ -132,28 +410,28 @@
\appendtoks
% \setevalue{\e!next \currenthead}{\donexthead [\currenthead]}%
- \setevalue{\e!start\currenthead}{\dostarthead[\currenthead]}%
- \setevalue{\e!stop \currenthead}{\dostophead [\currenthead]}%
+ \setuevalue{\e!start\currenthead}{\strc_sectioning_start[\currenthead]}%
+ \setuevalue{\e!stop \currenthead}{\strc_sectioning_stop [\currenthead]}%
\to \everydefinehead
\appendtoks
\doifelse{\headparameter\c!ownnumber}\v!yes
- {\setevalue\currenthead{\dohandleheadown[\currenthead]}}
- {\setevalue\currenthead{\dohandleheadnop[\currenthead]}}%
+ {\setuevalue\currenthead{\strc_sectioning_handle_own[\currenthead]}}
+ {\setuevalue\currenthead{\strc_sectioning_handle_nop[\currenthead]}}%
\to \everysetuphead
\let\currentnamedsection\empty
\unexpanded\def\startnamedsection
- {\dotripleempty\dostartnamedsection}
+ {\dotripleempty\strc_sectioning_start_named_section}
-\def\dostartnamedsection[#1]% [#2][#3]
+\unexpanded\def\strc_sectioning_start_named_section[#1]% [#2][#3]
{\pushmacro\currentnamedsection
\edef\currentnamedsection{#1}%
- \normalexpanded{\dodostarthead[\currentnamedsection]}} % [#2][#3]
+ \normalexpanded{\strc_sectioning_start_named_section_indeed[\currentnamedsection]}} % [#2][#3]
\unexpanded\def\stopnamedsection
- {\normalexpanded{\dostophead[\currentnamedsection]}%
+ {\normalexpanded{\strc_sectioning_stop[\currentnamedsection]}%
\popmacro\currentnamedsection}
% structure sections (the parents of chapter etc)
@@ -169,20 +447,38 @@
\def\resetcurrentstructuremarks {\resetmarking[\lastsectionname]} % will become option
%def\resetcurrentstructuremarkswithpage{\resetmarking[\lastsectionname]} % will become option
-% -2=text -1=manual 0=block 1+=structurelevel
+% We could use a commandhandler here but sections are somewhat special in the
+% sense that we have two ways of chaining: the main section (levels) as well
+% as rendering (head).
-\newcount\maxstructuredepth
+% -2 = text
+% -1 = manual
+% 0 = block
+% +1 = structurelevel 1 .. n
-\def\setnextsectionlevel#1%
- {\global\advance\maxstructuredepth\plusone
- \setevalue{\??headlevel#1}{\the\maxstructuredepth}}
+\newcount\maxstructuredepth
\def\sectionlevel#1%
{\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname}
+\def\namedsectionlevel#1#2% direct indirect
+ {\csname\??headlevel
+ \ifcsname\??headlevel#1\endcsname
+ #1%
+ \else\ifcsname\??headlevel#2\endcsname
+ #2%
+ \else
+ \v!none
+ \fi\fi
+ \endcsname}
+
+\def\xthenamedheadlevel#1%
+ {\namedsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}}
+
\setvalue{\??headlevel\v!block}{0}
\setvalue{\??headlevel\v!none }{-1}
\setvalue{\??headlevel\v!text }{-2}
+\setvalue{\??headlevel\v!head }{-3}
\newtoks\everydefinesection
@@ -190,14 +486,15 @@
{\ifcsname\??headlevel#1\endcsname \else
\edef\currentsection{#1}% not used, will go
\edef\currenthead{#1}%
- \setnextsectionlevel{#1}%
+ \global\advance\maxstructuredepth\plusone
+ \setevalue{\??headlevel#1}{\the\maxstructuredepth}%
\setstructurelevel{#1}{\sectionlevel{#1}}%
\normalexpanded{\setheadparameter{\s!parent}{\??head\lastsectionname}}% TO BE CHECKED, WE HAVE A HELPER
\the\everydefinesection
% so far for these default inheritances
\definemarking[#1]%
\ifnum\maxstructuredepth>\plusone
- \normalexpanded{\noexpand\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child
+ \normalexpanded{\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child
\fi
\xdef\lastsectionname{#1}%
\ifx\firstsectionname\empty
@@ -206,16 +503,16 @@
\fi}
\unexpanded\def\setupsection
- {\dotripleempty\dosetupsection}
+ {\dotripleempty\strc_sectioning_setup}
-\def\dosetupsection[#1][#2][#3]%
+\def\strc_sectioning_setup[#1][#2][#3]%
{\ifcsname\??headlevel#1\endcsname
- \dodosetupsection[#1][#2][#3]%
+ \strc_sectioning_setup_indeed[#1][#2][#3]%
\else
- \dodosetupsection[\sectionheadsection{#1}][#2][#3]%
+ \strc_sectioning_setup_indeed[\sectionheadsection{#1}][#2][#3]%
\fi}
-\def\dodosetupsection[#1][#2][#3]%
+\def\strc_sectioning_setup_indeed[#1][#2][#3]%
{\pushmacro\currenthead
\ifthirdargument
\edef\currenthead{#1#2}% % not used at any more in mkiv (sets now)
@@ -251,42 +548,42 @@
% head construction
-\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
+\unexpanded\def\strc_sectioning_handle_own{\dodoubleempty\strc_sectioning_handle_own_indeed} % [ref] {nr} {title}
+\unexpanded\def\strc_sectioning_handle_nop{\dodoubleempty\strc_sectioning_handle_nop_indeed} % [ref] {title}
+\unexpanded\def\strc_sectioning_start {\dotripleempty\strc_sectioning_start_named_section_indeed} % [settings] [userdata] !!! also used at lua end
\newconditional\currentstructureown
\newtoks\everybeforehead % hook, todo: before/after keys
\newtoks\everyafterhead % hook, todo: before/after keys
-\unexpanded\def\dodohandleheadown[#1][#2]#3#4%
+\unexpanded\def\strc_sectioning_handle_own_indeed[#1][#2]#3#4%
{\settrue\currentstructureown
\triggerautostructurelevel
- \dohandlehead{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title --
+ \strc_sectioning_handle{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title --
-\unexpanded\def\dodohandleheadnop[#1][#2]% for taco: [key=value] variant
+\unexpanded\def\strc_sectioning_handle_nop_indeed[#1][#2]% for taco: [key=value] variant
{\setfalse\currentstructureown
\triggerautostructurelevel
- \doifassignmentelse{#2}\dodohandleheadnopA\dodohandleheadnopB{#1}{#2}}
+ \doifassignmentelse{#2}\strc_sectioning_handle_nop_indeed_yes\strc_sectioning_handle_nop_indeed_nop{#1}{#2}}
-\unexpanded\def\dodohandleheadnopA#1#2%
- {\dohandlehead{#1}{#2}{}}
+\unexpanded\def\strc_sectioning_handle_nop_indeed_yes#1#2%
+ {\strc_sectioning_handle{#1}{#2}{}}
-\unexpanded\def\dodohandleheadnopB#1#2#3%
- {\dohandlehead{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --
+\unexpanded\def\strc_sectioning_handle_nop_indeed_nop#1#2#3%
+ {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --
-\unexpanded\def\dodostarthead[#1][#2][#3]% for the moment no grouping, too annoying with page breaks
+\unexpanded\def\strc_sectioning_start_named_section_indeed[#1][#2][#3]% for the moment no grouping, too annoying with page breaks
{\setfalse\currentstructureown
%\globalpushmacro\currenthead % this does not work out well
\xdef\currenthead{#1}%
\setsystemmode\currenthead % new, also here now
\headparameter\c!beforesection % beware, no users vars set yet
\the\everybeforehead
- \dohandlehead{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here)
+ \strc_sectioning_handle{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here)
\headparameter\c!insidesection}
-\unexpanded\def\dostophead[#1]% !!! also used at lua end
+\unexpanded\def\strc_sectioning_stop[#1]% !!! also used at lua end
{\dostoptagged
\dostoptagged
%\globalpopmacro\currenthead % so we do a hard recover
@@ -295,70 +592,64 @@
\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
+\let\dostarthead\strc_sectioning_start % used at lua end
+\let\dostophead \strc_sectioning_stop % used at lua end
% \newconditional\structurereversesectionnumbers % todo: key/val
-\newconditional\headtolist
-\newconditional\headdoincrement
-\newconditional\headdoplace
-\newconditional\headleaveempty
-\newconditional\headhidden
-\newconditional\headshownumber
-\newconditional\headisdisplay
+\newconditional\c_strc_sectioning_to_list
+\newconditional\c_strc_sectioning_increment
+\newconditional\c_strc_sectioning_place
+\newconditional\c_strc_sectioning_empty
+\newconditional\c_strc_sectioning_hidden
+
+\newconditional\headshownumber % public
+\newconditional\headisdisplay % public
-\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}
+\setvalue{\??headincrement\v!yes }{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
+\setvalue{\??headincrement\v!no }{\setfalse\c_strc_sectioning_increment\setfalse\c_strc_sectioning_to_list}
+\setvalue{\??headincrement\v!list }{\setfalse\c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
+\setvalue{\??headincrement\s!empty}{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list}
-\def\setheadincrement
+\unexpanded\def\strc_sectioning_initialize_increment
{\edef\currentheadincrement{\headparameter\c!incrementnumber}%
\ifcsname\??headincrement\currentheadincrement\endcsname
\csname\??headincrement\currentheadincrement\endcsname
\else
- \settrue \headdoincrement\settrue \headtolist
+ \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list
% \filterheadnumber
\fi}
\def\filterheadnumber
- {\settrue\headdoincrement
- \settrue\headtolist
+ {\settrue\c_strc_sectioning_increment
+ \settrue\c_strc_sectioning_to_list
\ifx\currentproduct\empty
% todo : filter from other toc (number, file, title)
% use : \currentheadincrement as spec
\fi}
\setvalue{\??headplace\v!yes}%
- {\setfalse\headleaveempty
- \settrue \headdoplace
- \setfalse\headhidden}
+ {\setfalse\c_strc_sectioning_empty
+ \settrue \c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden}
\setvalue{\??headplace\v!empty}%
- {\settrue \headleaveempty
- \settrue \headdoplace
- \setfalse\headhidden}
+ {\settrue \c_strc_sectioning_empty
+ \settrue \c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden}
\setvalue{\??headplace\v!no}%
- {\settrue \headleaveempty
- \setfalse\headdoplace
- \setfalse\headhidden}
+ {\settrue \c_strc_sectioning_empty
+ \setfalse\c_strc_sectioning_place
+ \setfalse\c_strc_sectioning_hidden}
\setvalue{\??headplace\v!hidden}%
- {\settrue \headleaveempty
- \setfalse\headdoplace
- \settrue \headhidden}
+ {\settrue \c_strc_sectioning_empty
+ \setfalse\c_strc_sectioning_place
+ \settrue \c_strc_sectioning_hidden}
-\def\setheadplacement
- {\executeifdefined
- {\??headplace\headparameter\c!placehead}
- {\getvalue{\??headplace\v!yes}}}
-
-
-\ifdefined\setheaddisplay \else \let\setheaddisplay\relax \fi
+\unexpanded\def\strc_sectioning_initialize_placement
+ {\expandcheckedcsname\??headplace{\headparameter\c!placehead}\v!yes}
\newmode\v!sectionnumber
@@ -370,12 +661,18 @@
{\resetsystemmode\v!sectionnumber
\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\strc_sectioning_initialize_number
+ {\edef\p_number{\sectionblockparameter\c!number}%
+ \ifx\p_number\v!yes
+ \edef\p_number{\headparameter\c!number}%
+ \ifx\p_number\v!yes
+ \settrue\headshownumber
+ \else
+ \setfalse\headshownumber
+ \fi
+ \else
+ \setfalse\headshownumber
+ \fi}
\unexpanded\def\theheadsynchonization
{\currentstructuresynchronize}
@@ -416,45 +713,15 @@
\let\currentheadlevel \!!zerocount
\let\currentheadcounter \!!zerocount
-% here we could inherit as well but it's a bit complex
-
-\def\doregisterhead#1#2#3% name data userdata
- {\structurecomponent
- %[\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\headdoincrement\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi,
- \c!bookmark=,
- \c!marking=,
- \c!list=,
- \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\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%
+\unexpanded\def\placeheadtext {\dosingleempty\strc_sectioning_place_head_text } % use with care
+\unexpanded\def\placeheadnumber{\dosingleempty\strc_sectioning_place_head_number} % use with care
+
+
+\unexpanded\def\strc_sectioning_report{\ctxlua{structures.sections.reportstructure()}}
+
+\ifdefined\strc_rendering_initialize_style_and_color \else
+
+ \unexpanded\def\strc_rendering_initialize_style_and_color#1#2%
{\dontconvertfont
\useheadstyleandcolor\c!style\c!color
\useheadstyleandcolor#1#2%
@@ -462,131 +729,134 @@
\fi
-\def\strc_sections_place_head_text[#1]%
+\def\strc_sectioning_place_head_text[#1]%
{\dontleavehmode
\begingroup
+ \settrue\headisdisplay % triggers interlinespace checking
\edef\currenthead{#1}%
- \setupheadcomponentfont\c!textstyle\c!textcolor
+ \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor
\relax
\getspecificstructuretitle{\thenamedheadlevel{#1}}%
\endgraf
\endgroup}
-\def\strc_sections_place_head_number[#1]%
+\def\strc_sectioning_place_head_number[#1]%
{\dontleavehmode
\begingroup
+ \settrue\headisdisplay % triggers interlinespace checking
\edef\currenthead{#1}%
- \setupheadcomponentfont\c!numberstyle\c!numbercolor
+ \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor
\relax
\getfullstructurenumber{\thenamedheadlevel{#1}}%
\endgraf
\endgroup}
-\ifdefined\presetnumberheadalternative \else \let\presetnumberheadalternative\relax \fi
-\ifdefined\setautostructurelevel \else \let\setautostructurelevel \relax \fi
-\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel \relax \fi
+\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi
-\def\dohandlehead#1#2#3% name data userdata (we can move #1 to the caller)
+\def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller)
{\xdef\currenthead {#1}%
\xdef\currentheadcoupling{\sectionheadcoupling\currenthead}%
\xdef\currentheadsection {\sectionheadsection \currentheadcoupling}%
\xdef\currentheadlevel {\sectionlevel \currentheadsection}%
- %writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}%
%
- \setautostructurelevel
- \setheadincrement
- \setheadplacement
- \setheaddisplay
- \setheadnumber
+ %\writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}%
+ %
+ \strc_sectioning_initialize_autolevel
+ \strc_sectioning_initialize_increment
+ \strc_sectioning_initialize_placement
+ \strc_sectioning_initialize_number
+ %
+ \unexpanded\def\\{\space}% messy here
%
- \unexpanded\def\\{\space}%
\flushingcolumnfloatsfalse
%
% todo: also mark (for header)
%
% we might remove the lower level
%
- % not here, after optional \page: \doregisterhead\currenthead{#2}{#3}%
+ % not here, after optional \page: \strc_sectioning_register{#1}{#2}{#3}%
%
% \xdef\currentheadcounter{\currentsectioncountervalue}% lua call
%
% \currentstructuresynchronize % will move
%
- \edef\numberheaddistance {\headparameter\c!distance }% compatibility
- \edef\numberheadalternative{\headparameter\c!alternative}% compatibility
- \presetnumberheadalternative
- %
\let\getheadnumber\empty
\let\getheadtitle \empty
\let\getheadsyncs \empty
- \ifconditional\headdoincrement
- \ifconditional\headdoplace
- \doheadspacingbeforeyes
- \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \ifconditional\c_strc_sectioning_increment
+ \ifconditional\c_strc_sectioning_place
+ \strc_sectioning_before_yes
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
\let\getheadsyncs\theheadsynchonization
\let\getheadtitle\fullheadtitle
\ifconditional\headshownumber
\let\getheadnumber\fullheadnumber
- \placecurrentheadnumbertext
+ \strc_rendering_place_head_number_and_text
\else
- \placecurrentheadtext
+ \strc_rendering_place_head_text
\fi
- \doheadspacingafteryes
- \else\ifconditional\headhidden
- \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \strc_sectioning_after_yes
+ \else\ifconditional\c_strc_sectioning_hidden
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
\let\getheadsyncs\theheadsynchonization
- \placecurrentheadhidden % only something when tracing
+ \strc_rendering_place_head_hidden % only something when tracing
\else
- \doheadspacingbeforenop % toegevoegd ivm subpaginanr / tug sheets
- \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \strc_sectioning_before_nop % toegevoegd ivm subpaginanr / tug sheets
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
\let\getheadsyncs\theheadsynchonization
- \placecurrentheadempty % just flush 'm
- \doheadspacingafternop
+ \strc_rendering_place_head_empty % just flush 'm
+ \strc_sectioning_after_nop
\fi\fi
\else
- \ifconditional\headdoplace
- \doheadspacingbeforeyes
- \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \ifconditional\c_strc_sectioning_place
+ \strc_sectioning_before_yes
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
\let\getheadsyncs\theheadsynchonization
\let\getheadtitle\fullheadtitle
- \placecurrentheadtext
- \doheadspacingafteryes
- \else\ifconditional\headhidden
- \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \strc_rendering_place_head_text
+ \strc_sectioning_after_yes
+ \else\ifconditional\c_strc_sectioning_hidden
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
\let\getheadsyncs\theheadsynchonization
- \placecurrentheadhidden % only something when tracing
+ \strc_rendering_place_head_hidden % only something when tracing
\else
% do nothing / should be vbox to 0pt
- \doheadspacingbeforenop
- \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \strc_sectioning_before_nop
+ \strc_sectioning_register{#1}{#2}{#3}% after optional \page
+ \strc_sectioning_report
\let\getheadsyncs\theheadsynchonization
- \placecurrentheadempty % just flush 'm
- \doheadspacingafternop
+ \strc_rendering_place_head_empty % just flush 'm
+ \strc_sectioning_after_nop
\fi\fi
\fi
\flushingcolumnfloatstrue
- \setfalse\ignorehandlepagebreak
+ \setfalse\c_strc_sectioniong_ignore_page
% ignorespaces prevents spaces creeping in when after=\dontleavehmode
\dostarttagged\t!sectioncontent\empty
- \ifconditional\headisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay
\ignorespaces
\else
\expandafter\GotoPar
\fi}
-% typesetting
+% typesetting (the getters are public)
-\unexpanded\def\placecurrentheadnumbertext
+\unexpanded\def\strc_rendering_place_head_number_and_text
{\setheadmarking
\getheadnumber/\getheadtitle
\getheadsyncs}
-\unexpanded\def\placecurrentheadtext
+\unexpanded\def\strc_rendering_place_head_text
{\setheadmarking
\getheadtitle
\getheadsyncs}
-\unexpanded\def\placecurrentheadempty
+\unexpanded\def\strc_rendering_place_head_empty
{\setheadmarking
\getheadsyncs}
@@ -596,7 +866,7 @@
% todo: when in the page builder we need to resolve the marking immediately
% because otherwise we have an async
-\unexpanded\def\placecurrentheadhidden % maybe trialtypesetting check
+\unexpanded\def\strc_rendering_place_head_hidden % maybe trialtypesetting check
{\setxvalue{\??hiddenheadattr\currenthead}%
{\headreferenceattributes}% can be used when making a box
\setxvalue{\??hiddenheadsync\currenthead}%
@@ -625,138 +895,144 @@
% pagebreaks
-\newcount\precedingstructurelevel \precedingstructurelevel\plusone
-\newconditional\ignorehandlepagebreak
+\letvalue{\??headmarknop\v!page }\donothing
+\setvalue{\??headmarknop\v!reset }{\resetcurrentstructuremarks}
+\letvalue{\??headmarknop\s!unknown}\donothing
+
+\letvalue{\??headmarkyes\v!page }\donothing % to be checked: {\resetcurrentstructuremarks}
+\setvalue{\??headmarkyes\v!reset }{\resetcurrentstructuremarks}
+\letvalue{\??headmarkyes\s!unknown}\donothing
+
+\def\strc_sectioning_check_layout
+ {\edef\p_page{\headparameter\c!page}%
+ \ifx\p_page\empty
+ \strc_sectioning_check_layout_nop
+ \else
+ \strc_sectioning_check_layout_yes
+ \fi}
+
+\def\strc_sectioning_check_layout_nop
+ {\expandcheckedcsname\??headmarknop{\headparameter\c!marking}\s!unknown}
+
+\def\strc_sectioning_check_layout_yes
+ {\page[\p_page]%
+ \expandcheckedcsname\??headmarkyes{\headparameter\c!marking}\s!unknown
+ \edef\p_header{\headparameter\c!header}%
+ \ifx\p_header\empty \else
+ \doifelselayouttextline\v!header{\normalexpanded{\setuplayouttext[\v!header][\c!state=\p_header]}}\donothing
+ \fi
+ \edef\p_text{\headparameter\c!text}%
+ \ifx\p_text\empty \else
+ \doifelselayouttextline\v!text {\normalexpanded{\setuplayouttext[\v!text ][\c!state=\p_text ]}}\donothing
+ \fi
+ \edef\p_footer{\headparameter\c!footer}%
+ \ifx\p_footer\empty \else
+ \doifelselayouttextline\v!footer{\normalexpanded{\setuplayouttext[\v!footer][\c!state=\p_footer]}}\donothing
+ \fi}
+
+\newcount \c_strc_sectioniong_preceding_level \c_strc_sectioniong_preceding_level\plusone
+\newconditional\c_strc_sectioning_auto_break \settrue\c_strc_sectioning_auto_break
+\newconditional\c_strc_sectioniong_ignore_page
+\newsignal \s_strc_sectioniong_continuous_signal
-\def\doheadspacingbeforeyes
- {\docheckheadbefore
- \dohandleheadpagebreakyes
+\unexpanded\def\strc_sectioning_inject_continuous_signal
+ {\ifhmode
+ \hskip\s_strc_sectioniong_continuous_signal\relax
+ \fi}
+
+\def\strc_sectioning_before_yes
+ {\strc_sectioning_check_before\strc_sectioning_handle_page_yes
\headparameter\c!inbetween
\dostarttagged\t!section\currenthead}
-\def\doheadspacingbeforenop
- {\docheckheadbefore
- \dohandleheadpagebreaknop
+\def\strc_sectioning_before_nop
+ {\strc_sectioning_check_before\strc_sectioning_handle_page_nop
\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
+\def\strc_sectioning_empty_correction
+ {\ifconditional\c_strc_sectioning_empty
+ % this needs checking
+ \penalty\plustenthousand
\vskip-\lineheight
\kern\zeropoint
\prevdepth\strutdepth
\fi}
-\def\doheadspacingafteryes
+\def\strc_sectioning_after_yes
{\ifconditional\headisdisplay
- \dosomebreak\nobreak % needs to be adapted to vspacing
- \emptyheadcorrection
+ \ifconditional\c_strc_sectioning_auto_break
+ \vspacing[\v!samepage-\currentheadlevel]%
+ \fi
+ \strc_sectioning_empty_correction
\headparameter\c!after
\fi}
-\def\doheadspacingafternop
+\def\strc_sectioning_after_nop
{}
-\newsignal\continuousheadsignal
-
-\def\docheckheadbefore#1%
+\def\strc_sectioning_check_before#1%
{\ifhmode
- \scratchcounter\lastpenalty\unpenalty % no beauty in this
- \ifdim\lastskip=\continuousheadsignal
+ \scratchcounter\lastpenalty
+ \unpenalty % no beauty in this
+ \ifdim\lastskip=\s_strc_sectioniong_continuous_signal
% no page break
- \ifconditional\ignorehandlepagebreak
- \setfalse\ignorehandlepagebreak
+ \ifconditional\c_strc_sectioniong_ignore_page
+ \setfalse\c_strc_sectioniong_ignore_page
\else
- \global\precedingstructurelevel\currentheadlevel
+ \global\c_strc_sectioniong_preceding_level\currentheadlevel
\nobreak
\fi
- \global\settrue\continuoussectionhead
+ \global\settrue\c_strc_rendering_continuous
\else
\penalty\scratchcounter
- \global\setfalse\continuoussectionhead
+ \global\setfalse\c_strc_rendering_continuous
#1%
\fi
\else
- \global\setfalse\continuoussectionhead
+ \global\setfalse\c_strc_rendering_continue
#1%
\fi}
-\def\dodocheckheadlayout#1#2%
- {\doifelselayouttextline{#1}
- {\doifsomething{\headparameter#2}{\expanded{\setuplayouttext[#1][\c!state=\headparameter#2]}}}
- \donothing}
-
-\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}%
- {\docheckheadlayout}}
+\def\strc_sectioning_handle_page_nop
+ {\edef\p_continue{\headparameter\c!continue}%
+ \ifx\p_continue\v!yes
+ \ifnum\previoussectioncountervalue=\zerocount
+ \strc_sectioning_check_layout
+ \else\ifnum\currentsectioncountervalue>\zerocount
+ \strc_sectioning_check_layout
+ \fi\fi
+ \else
+ \strc_sectioning_check_layout
+ \fi}
-\def\dohandleheadpagebreakyes
+\def\strc_sectioning_handle_page_yes
{%[[\currenthead @\thenamedheadlevel\currenthead/prev:\previoussectioncountervalue/curr:\currentsectioncountervalue]]
- \ifconditional\ignorehandlepagebreak
- \setfalse\ignorehandlepagebreak
+ \ifconditional\c_strc_sectioniong_ignore_page
+ \setfalse\c_strc_sectioniong_ignore_page
\else
-% \ifnum\lastpenalty>\zerocount
-% \global\pagebreakdisabledtrue
-% \fi
% beware, these numbers are not yet know here
- \doifelse{\headparameter\c!continue}\v!yes
- {\ifnum\previoussectioncountervalue=\zerocount
- \docheckheadlayout
- \else\ifnum\currentsectioncountervalue>\zerocount
- \docheckheadlayout
- \fi\fi}%
- {\docheckheadlayout}%
- \doifnot{\headparameter\c!aligntitle}\v!float\page_otr_command_flush_side_floats
- \headparameter\c!before
- \relax
-% \ifpagebreakdisabled
-% \global\pagebreakdisabledfalse
-% \else
-% \dopreventbreakafterheadauto % not ok as it binds the prev par
-% \fi
- \doif{\headparameter\c!aligntitle}\v!float\indent
- \global\precedingstructurelevel\currentheadlevel
- \fi}
-
-\settrue\autoheadbreak % todo: \vspacing[category:8] == keep_together
-
-\def\dopreventbreakafterheadauto % used after \c!before
- {\ifconditional\autoheadbreak
- \vspacing[\v!samepage-\currentheadlevel]%
+ \strc_sectioning_handle_page_nop
+ \edef\p_aligntitle{\headparameter\c!aligntitle}%
+ \ifx\p_aligntitle\v!float
+ \headparameter\c!before\relax
+ \indent
+ \else
+ \page_otr_command_flush_side_floats
+ \headparameter\c!before\relax
+ \fi
+ \global\c_strc_sectioniong_preceding_level\currentheadlevel
\fi}
-\def\dopreventbreakafterheadspec#1% see enumerations etc
- {\ifconditional\autoheadbreak
- \vspacing[\v!samepage-\the\numexpr\currentheadlevel+1\relax]% todo #1
+\unexpanded\def\strc_sectioning_prevent_page_break#1% see strc-con
+ {\ifconditional\c_strc_sectioning_auto_break
+ \vspacing[\v!samepage-\the\numexpr\currentheadlevel+\ifx#1\empty\plusone\else#1\fi\relax]%
\fi}
-\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
+% We do support negative numbers but it can have side effects that we won't catch:
%
% \chapter{some} \setupheadnumber[chapter][3] \chapter{more}
% \setupheadnumber[section][8] \section{b} \section{c} \setupheadnumber[section][-1] \section{d}
@@ -765,9 +1041,9 @@
{\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}}
\unexpanded\def\setupheadnumber
- {\dodoubleargument\dosetupheadnumber}
+ {\dodoubleargument\strc_sectioning_setup_number}
-\def\dosetupheadnumber[#1][#2]% todo: reset if at other level
+\def\strc_sectioning_setup_number[#1][#2]% todo: reset if at other level
{\setstructurenumber{\thenamedheadlevel{#1}}{#2}}
\def\currentheadnumber{0} % ==> \currentheadnumber
@@ -781,15 +1057,15 @@
\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}}
\unexpanded\def\headnumber
- {\dodoubleempty\doheadnumber}
+ {\dodoubleempty\strc_sectioning_number}
-\def\doheadnumber[#1][#2]% simple case is just a number
+\def\strc_sectioning_number[#1][#2]% simple case is just a number
{\getsomefullstructurenumber{\iffirstargument\thenamedheadlevel{#1}\fi}{#2}}
-\def\someheadnumber
- {\dodoubleempty\dosomeheadnumber}
+\unexpanded\def\someheadnumber
+ {\dodoubleempty\strc_sectioning_number_some}
-\def\dosomeheadnumber[#1][#2]%
+\def\strc_sectioning_number_some[#1][#2]%
{\dontleavehmode
\begingroup
\edef\currenthead{#1}%
@@ -807,22 +1083,22 @@
% experimental
-\newconditional\c_strc_sections_auto_levels
+\newconditional\c_strc_sectioning_auto_levels
\appendtoks
- \settrue\c_strc_sections_auto_levels
+ \settrue\c_strc_sectioning_auto_levels
\to \everyenableelements
-\def\setautostructurelevel
- {\ifconditional\c_strc_sections_auto_levels
+\unexpanded\def\strc_sectioning_initialize_autolevel
+ {\ifconditional\c_strc_sectioning_auto_levels
\ctxcommand{autonextstructurelevel(\number\currentheadlevel)}%
- \global\setfalse\c_strc_sections_auto_levels
+ \global\setfalse\c_strc_sectioning_auto_levels
\fi}
-\def\triggerautostructurelevel
- {\global\settrue\c_strc_sections_auto_levels}
+\unexpanded\def\triggerautostructurelevel
+ {\global\settrue\c_strc_sectioning_auto_levels}
-\def\finalizeautostructurelevels
+\unexpanded\def\finalizeautostructurelevels
{\ctxcommand{autofinishstructurelevels()}}
\unexpanded\def\finalizeautostructurelevel
diff --git a/tex/context/base/strc-syn.lua b/tex/context/base/strc-syn.lua
index c2b5251d0..ca4b3ac18 100644
--- a/tex/context/base/strc-syn.lua
+++ b/tex/context/base/strc-syn.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['str-syn'] = {
+if not modules then modules = { } end modules ['strc-syn'] = {
version = 1.001,
comment = "companion to str-syn.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/tex/context/base/strc-syn.mkiv b/tex/context/base/strc-syn.mkiv
index 535eab04b..e0087d450 100644
--- a/tex/context/base/strc-syn.mkiv
+++ b/tex/context/base/strc-syn.mkiv
@@ -65,8 +65,8 @@
%\c!headcolor=,
%\c!criterium=,
\c!location=\v!left,
- \c!width=5em,
- \c!distance=0pt,
+ \c!width=5\emwidth,
+ \c!distance=\zeropoint,
%\c!sample=,
%\c!hang=,
%\c!align=,
diff --git a/tex/context/base/strc-tag.lua b/tex/context/base/strc-tag.lua
index 78b807487..7e5c6f993 100644
--- a/tex/context/base/strc-tag.lua
+++ b/tex/context/base/strc-tag.lua
@@ -161,6 +161,7 @@ local properties = allocate {
metadata = { pdf = "Div", nature = "display" },
metavariable = { pdf = "Span", nature = "mixed" },
+ mid = { pdf = "Span", nature = "inline" },
sub = { pdf = "Span", nature = "inline" },
sup = { pdf = "Span", nature = "inline" },
subsup = { pdf = "Span", nature = "inline" },
diff --git a/tex/context/base/strc-tag.mkiv b/tex/context/base/strc-tag.mkiv
index 84d6fb2d3..6563e884e 100644
--- a/tex/context/base/strc-tag.mkiv
+++ b/tex/context/base/strc-tag.mkiv
@@ -126,6 +126,7 @@
\def\t!ignore {ignore} % Span
+\def\t!mid {mid} % Span
\def\t!sub {sub} % Span
\def\t!sup {sup} % Span
\def\t!subsup {subsup} % Span
@@ -332,4 +333,12 @@
\unexpanded\def\settaggedmetadata[#1]%
{\ctxlua{structures.tags.registermetadata(\!!bs#1\!!es)}}
+%D An overload:
+
+\let\strc_tagged_saved_bpar\bpar
+\let\strc_tagged_saved_epar\epar
+
+\unexpanded\def\bpar{\dostarttagged\t!paragraph\empty\strc_tagged_saved_bpar}
+\unexpanded\def\epar{\strc_tagged_saved_epar\dostoptagged}
+
\protect
diff --git a/tex/context/base/supp-ali.mkiv b/tex/context/base/supp-ali.mkiv
deleted file mode 100644
index 54a7b77e4..000000000
--- a/tex/context/base/supp-ali.mkiv
+++ /dev/null
@@ -1,173 +0,0 @@
-%D \module
-%D [ file=supp-ali,
-%D version=2000.04.17,
-%D title=\CONTEXT\ Support Macros,
-%D subtitle=Alignment,
-%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 Yet undocumented.
-
-% 0 = centered
-% 1 = left in before
-% 2 = right in before
-% 3 = left in after
-% 4 = right in after
-
-\unprotect
-
-% \starttabulate[|cg{.}|cg{,}|cg{,}|]
-% \NC period \NC comma \NC comma \NC\NR
-% \NG 100.000,00 \NG 100.000,00 \NG 100,00 \NC\NR
-% \NG 10.000,00 \NG 10.000,00 \NG 1000,00 \NC\NR
-% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
-% \NG 100,00 \NG 100,00 \NG 10,00 \NC\NR
-% \NG 10\\ \NG 10\\ \NG 0,00 \NC\NR
-% \NG 10 \NG 10 \NG 0,00 \NC\NR
-% \NG 10 \NG 10 \NG 0,00 \NC\NR
-% \stoptabulate
-
-\chardef\characteralignmentmode=4
-\chardef\characteralignmentslot=1
-
-\newtoks\@@characteralignlst
-
-\let\afterassignwidth \!!zeropoint
-\let\beforeassignwidth\!!zeropoint
-
-\def\alignmentcharacter{.}
-
-\let\alignmentclass\s!default % can be used to handle multiple mixed ones
-
-\def\setfirstpasscharacteralign
- {\popcharacteralign
- \expanded{\dosetfirstpasscharacteralign{\alignmentcharacter}}}
-
-\def\dosetfirstpasscharacteralign#1%
- {\def\checkalignment##1%
- {\popcharacteralign
- \let\\\empty
- \setbox\scratchbox\hbox{#1}%
- \edef\characterassignwidth{\the\wd\scratchbox}%
- \setbox\scratchbox\emptyhbox
- \docheckalignment##1#1\relax\relax
- \scratchdimen-\wd\scratchbox
- \setbox\scratchbox\hbox{\ignorespaces##1\unskip}%
- \advance\scratchdimen \wd\scratchbox
- \ifdim\scratchdimen>\beforeassignwidth\relax
- \edef\beforeassignwidth{\the\scratchdimen}%
- \fi
- \ifdim\scratchdimen=\zeropoint
- \setbox\scratchbox\hbox{\ignorespaces##1\unskip}%
- \scratchdimen\wd\scratchbox
- \ifcase\characteralignmentmode
- % do nothing
- \else\ifnum\characteralignmentmode<\plusthree
- \advance\scratchdimen \characterassignwidth
- \ifdim\scratchdimen>\beforeassignwidth\relax
- \edef\beforeassignwidth{\the\scratchdimen}%
- \fi
- \else
- \ifdim\scratchdimen>\afterassignwidth\relax
- \edef\afterassignwidth{\the\scratchdimen}%
- \fi
- \fi\fi
- \fi
- \pushcharacteralign}%
- \def\docheckalignment##1#1##2##3\relax
- {\ifx##2\relax
- \setbox\scratchbox\hbox{\ignorespaces##1\unskip}%
- \ifdim\wd\scratchbox>\afterassignwidth
- \edef\afterassignwidth{\the\wd\scratchbox}%
- \fi
- \else
- \docheckalignment##2##3\relax\relax
- \fi}}
-
-\def\setsecondpasscharacteralign
- {\popcharacteralign
- \expanded{\dosetsecondpasscharacteralign{\alignmentcharacter}}}
-
-\def\dosetsecondpasscharacteralign#1%
- {\def\checkalignment##1%
- {\popcharacteralign
- \let\\\empty % beware, no grouping
- \setbox\scratchbox\hbox{#1}%
- \edef\characterassignwidth{\the\wd\scratchbox}%
- \setbox\scratchbox\emptyhbox
- % new 12,34 vs 10\\ where 10 aligns on 12 if #1 = ,
- \ifcase\characteralignmentslot
- \docheckalignment##1#1\relax\relax
- \scratchdimen\wd\scratchbox
- \setbox\scratchbox\hbox{\ignorespaces##1\unskip}%
- \else
- \def\\{#1}%
- \expanded{\docheckalignment##1#1\relax\relax}%
- \scratchdimen\wd\scratchbox
- \setbox\scratchbox\hbox{\def\\{\hphantom{#1}}\ignorespaces##1\unskip}%
- \fi
- \noindent
- \ifdim\scratchdimen=\wd\scratchbox
- \ifcase\characteralignmentmode
- \box\scratchbox
- \else
- \hbox
- {\dontcomplain
- \hbox to \beforeassignwidth
- {\ifcase\characteralignmentmode\or
- \box\scratchbox\hss
- \or
- \hss\box\scratchbox\hskip\characterassignwidth
- \or
- \hss\rlap{\box\scratchbox}%
- \or
- \hss\rlap{\hbox to \afterassignwidth{\hss\box\scratchbox}}%
- \fi}%
- \hskip\afterassignwidth}%
- \fi
- \else
- \hbox
- {\hbox to \beforeassignwidth
- {\hss\box\scratchbox\hskip-\scratchdimen}%
- \hskip\afterassignwidth}%
- \fi}%
- \def\docheckalignment##1#1##2##3\relax
- {\ifx##2\relax
- \setbox\scratchbox\hbox{\ignorespaces##1\unskip}%
- \else
- \docheckalignment##2##3\relax\relax
- \fi}}
-
-% provide a means to use multiple alignments mixed
-
-\def\pushcharacteralign
- {\ifcsname @cac@\alignmentclass\endcsname\else
- \doglobal\appendetoks\noexpand\do{\alignmentclass}\to\@@characteralignlst
- \fi
- \setxvalue{@cac@\alignmentclass}{\noexpand\do
- {\afterassignwidth}{\beforeassignwidth}{\alignmentcharacter}}}
-
-\def\popcharacteralign
- {\def\do##1##2##3%
- {\def\afterassignwidth {##1}%
- \def\beforeassignwidth {##2}%
- \def\alignmentcharacter{##3}}%
- \executeifdefined{@cac@\alignmentclass}\donothing}
-
-\def\resetcharacteralign % does not work well nested
- {\def\do##1{\global\letbeundefined{@cac@##1}}% global !
- \the\@@characteralignlst
- \global\@@characteralignlst\emptytoks}
-
-\long\def\startcharacteralign#1\stopcharacteralign
- {\bgroup
- \setfirstpasscharacteralign #1%
- \setsecondpasscharacteralign#1%
- \egroup}
-
-\protect \endinput
diff --git a/tex/context/base/supp-box.lua b/tex/context/base/supp-box.lua
index 853de4cbe..c7382834a 100644
--- a/tex/context/base/supp-box.lua
+++ b/tex/context/base/supp-box.lua
@@ -10,6 +10,9 @@ if not modules then modules = { } end modules ['supp-box'] = {
local report_hyphenation = logs.reporter("languages","hyphenation")
+local tex, node = tex, node
+local context, commands, nodes = context, commands, nodes
+
local nodecodes = nodes.nodecodes
local disc_code = nodecodes.disc
@@ -19,6 +22,7 @@ local glue_code = nodecodes.glue
local glyph_code = nodecodes.glyph
local new_penalty = nodes.pool.penalty
+
local free_node = node.free
local copynodelist = node.copy_list
local copynode = node.copy
@@ -65,10 +69,9 @@ local function applytochars(list,what,nested)
while current do
local id = current.id
if nested and (id == hlist_code or id == vlist_code) then
- context.hbox()
- context.bgroup()
+ context.beginhbox()
applytochars(current.list,what,nested)
- context.egroup()
+ context.endhbox()
elseif id ~= glyph_code then
noaction(copynode(current))
else
@@ -92,8 +95,7 @@ local function applytowords(list,what,nested)
end
noaction(copynode(current))
elseif nested and (id == hlist_code or id == vlist_code) then
- context.hbox()
- context.bgroup()
+ context.beginhbox()
applytowords(current.list,what,nested)
context.egroup()
elseif not start then
diff --git a/tex/context/base/supp-box.mkiv b/tex/context/base/supp-box.mkiv
index de1da677a..a8774e482 100644
--- a/tex/context/base/supp-box.mkiv
+++ b/tex/context/base/supp-box.mkiv
@@ -75,9 +75,10 @@
%D core macros \type {\strutdepth} and alike, which are
%D values.
-\def\strutdp{\dp\strutbox}
-\def\strutht{\ht\strutbox}
-\def\strutwd{\wd\strutbox}
+\def\strutdp {\dp\strutbox}
+\def\strutht {\ht\strutbox}
+\def\strutwd {\wd\strutbox}
+\def\struthtdp{\dimexpr\ht\strutbox+\dp\strutbox\relax}
%D \macros
%D {voidbox,nextbox}
@@ -1236,7 +1237,7 @@
\ifdone \else
\parfillskip\zeropoint
\rightskip\zeropoint
- \hskip\zeropoint \!!plus 1\!!fill % \hsize
+ \hskip\zeropoint \s!plus 1\s!fill % \hsize
\fi
\unhcopy0}%
\ifdim\ht\nextbox>\strutht
@@ -1423,12 +1424,27 @@
{\setbox\nextbox\hbox
{\strut
\dp\nextbox\zeropoint
- \lower\strutdepth\box\nextbox}%
- \dp\nextbox\strutdepth
- \ht\nextbox\strutheight
+ \lower\strutdp\box\nextbox}%
+ \dp\nextbox\strutdp
+ \ht\nextbox\strutht
\box\nextbox
\egroup}
+%D A variant on this:
+
+\unexpanded\def\inlinedbox
+ {\bgroup
+ \dowithnextbox
+ {\setbox\nextbox\hbox
+ {\lower
+ \dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax
+ \box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}%
+ \hbox}
+
%D \macros
%D {struttedbox}
%D
@@ -1513,8 +1529,8 @@
\bgroup
\dontcomplain
\forgetall
- \setbox0\hbox{\vrule\!!width \zeropoint#1}%
- \setbox2\vbox{\hrule\!!height\zeropoint#1}%
+ \setbox0\hbox{\vrule\s!width \zeropoint#1}%
+ \setbox2\vbox{\hrule\s!height\zeropoint#1}%
\advance\vsize \ht2
\advance\hsize \wd0
\vbox to \vsize
@@ -1573,9 +1589,9 @@
{\bgroup
\dowithnextbox
{\setlocalhsize
- \setbox\scratchbox\hbox{\vrule\!!width \zeropoint#1}%
+ \setbox\scratchbox\hbox{\vrule\s!width \zeropoint#1}%
\ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi
- \setbox\scratchbox\vbox{\hrule\!!height\zeropoint#1}%
+ \setbox\scratchbox\vbox{\hrule\s!height\zeropoint#1}%
\ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi
\vbox to \vsize{\vss\hbox to \hsize{\hss\box\nextbox\hss}\vss}%
\egroup}%
@@ -1791,7 +1807,7 @@
\ifvoid\unhhedbox
\exitloop
\else
- \hskip\zeropoint \!!plus \zeropoint
+ \hskip\zeropoint \s!plus \zeropoint
\fi}%
\egroup}
@@ -2169,7 +2185,7 @@
\newbox\fakedboxcursor
\setbox\fakedboxcursor\hbox
- {\vrule\!!width\zeropoint\!!height\zeropoint\!!depth\zeropoint}
+ {\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
\unexpanded\def\boxcursor % overloaded in core-vis
{\iftraceboxplacement
@@ -2178,9 +2194,9 @@
\setbox\scratchbox\hbox to \zeropoint
{\hss
\vrule
- \!!width \scratchdimen
- \!!height\scratchdimen
- \!!depth \scratchdimen
+ \s!width \scratchdimen
+ \s!height\scratchdimen
+ \s!depth \scratchdimen
\hss}%
\smashedbox\scratchbox
\egroup
@@ -2431,15 +2447,14 @@
%D \macros
%D {makestrutofbox}
%D
-%D This macro sets the dimensions of a box to those of a
-%D strut.
+%D This macro sets the dimensions of a box to those of a strut.
\def\domakestrutofbox
{\ht\c_boxes_register\strutht
\dp\c_boxes_register\strutdp
\wd\c_boxes_register\zeropoint}
-\unexpanded\def\makestrutofbox
+\unexpanded\def\makestrutofbox % not used
{\afterassignment\domakestrutofbox\c_boxes_register}
%D \macros
@@ -2615,6 +2630,21 @@
% \showboxbreadth\maxdimen
% \showboxdepth \maxdimen
+%D Moved from cont-new:
+%D
+%D \starttyping
+%D \minimalhbox 100pt {test}
+%D \stoptyping
+
+\unexpanded\def\minimalhbox#1#%
+ {\dowithnextbox
+ {\bgroup
+ \setbox\scratchbox\hbox#1{\hss}%
+ \ifdim\wd\nextbox<\wd\scratchbox\wd\nextbox\wd\scratchbox\fi
+ \box\nextbox
+ \egroup}
+ \hbox}
+
\protect \endinput
% a bit of test code:
diff --git a/tex/context/base/supp-mat.mkiv b/tex/context/base/supp-mat.mkiv
index bc26611ae..f77ee3454 100644
--- a/tex/context/base/supp-mat.mkiv
+++ b/tex/context/base/supp-mat.mkiv
@@ -51,32 +51,27 @@
\let\normalstartimath \Ustartmath
\let\normalstopimath \Ustopmath
\let\normalstartdmath \Ustartdisplaymath
-\let\normalstopdmath \Ustopmath
+\let\normalstopdmath \Ustopdisplaymath
+
\def\normalmathaligntab{&} % \let\normalmathaligntab\aligntab does to work well in a let to & (a def works ok)
-\let\normalsuper \Usuperscript % obsolete
-\let\normalsuber \Usubscript % obsolete
-\let\startimath \Ustartmath % obsolete, less safe
-\let\stopimath \Ustopmath % obsolete, less safe
-\let\startdmath \Ustartdisplaymath % obsolete, less safe
-\let\stopdmath \Ustopmath % obsolete, less safe
+\let\normalsuper \Usuperscript % obsolete
+\let\normalsuber \Usubscript % obsolete
+
+\let\startimath \Ustartmath
+\let\stopimath \Ustopmath
+\let\startdmath \Ustartdisplaymath
+\let\stopdmath \Ustopmath
\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\m\mathematics
\let\stopmathmode\relax
-% \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
@@ -96,7 +91,12 @@
%D
%D An example of usage of the following can be found in the MathML module:
-\unexpanded\def\displaymathematics#1{\relax\ifmmode#1\else\dostartformula{}#1\dostopformula\fi}
+\ifdefined\strc_formulas_start_formula \else
+ \def\strc_formulas_start_formula{\normalstartdmath}
+ \def\strc_formulas_stop_formula {\normalstopdmath }
+\fi
+
+\unexpanded\def\displaymathematics#1{\relax\ifmmode#1\else\strc_formulas_start_formula{}#1\strc_formulas_stop_formula\fi}
\unexpanded\def\inlinemathematics {\dontleavehmode\mathematics}
\unexpanded\def\automathematics {\relax\ifhmode\expandafter\inlinemathematics\else\expandafter\displaymathematics\fi}
@@ -128,7 +128,8 @@
\def\dimensionhalfspace {\,}
\unexpanded\def\dimension#1%
- {\def\dodimensionsignal{\kern\dimensionsignal}%
+ {\pushmacro\dodimensionsignal
+ \gdef\dodimensionsignal{\kern\dimensionsignal}%
\ifdim\lastskip=\zeropoint\relax
\ifdim\lastkern=\zeropoint\relax
\ifmmode
@@ -144,70 +145,16 @@
\else
\unskip\mathematics{\dimensionhalfspace\dimensionhalfspace\dimensiontypeface#1}%
\fi
- \dodimensionsignal}
+ \dodimensionsignal
+ \popmacro\dodimensionsignal}
\unexpanded\def\nodimension#1%
{\unskip#1\global\let\dodimensionsignal\relax}
-% %D \macros
-% %D {super, suber}
-% %D
-% %D \TEX\ uses \type{^} and \type{_} for entering super- and
-% %D subscript mode. We want however a bit more control than
-% %D normally provided, and therefore provide \type {\super}
-% %D and \type{\suber} (\type {\sub} is already taken).
-%
-% \global\let\normalsuper=\normalsuperscript % will become obsolete
-% \global\let\normalsuber=\normalsubscript % will become obsolete
-%
-% \newcount\supersubmode
-%
-% \newevery\everysupersub \EverySuperSub
-%
-% \appendtoks \advance\supersubmode\plusone \to \everysupersub
-%
-% \def\super#1{\normalsuperscript{\the\everysupersub#1}}
-% \def\suber#1{\normalsubscript {\the\everysupersub#1}}
-%
-% %D \macros
-% %D {enablesupsub}
-% %D
-% %D We can let \type {^} and \type {_} act like \type {\super}
-% %D and \type {\suber} by saying \type {\enablesupsub}.
-%
-% \bgroup
-% \catcode\circumflexasciicode\activecatcode
-% \catcode\underscoreasciicode\activecatcode
-% \gdef\enablesupsub
-% {\catcode\circumflexasciicode\activecatcode
-% \catcode\underscoreasciicode\activecatcode
-% \def^{\ifmmode\expandafter\super\else\expandafter\normalsuper\fi}%
-% \def_{\ifmmode\expandafter\suber\else\expandafter\normalsuber\fi}}
-% \egroup
-%
-% %D \macros
-% %D {restoremathstyle}
-% %D
-% %D We can pick up the current math style by calling \type
-% %D {\restoremathstyle}.
-%
-% \def\restoremathstyle
-% {\ifmmode
-% \ifcase\supsubmode
-% \textstyle
-% \or
-% \scriptstyle
-% \else
-% \scriptscriptstyle
-% \fi
-% \fi}
-
%D \macros
%D {cramped}
%D
-%D \TEX provides no primitive to force in cramped math mode. Here is
-%D a macro that does so. It is based on a solution by Don Knuth (\useurl
-%D {http://www.ctan.org/tex-archive/digests/tex-implementors/042}).
+%D Cramped math:
%D
%D \startbuffer
%D \ruledhbox{$\left\{{x^2\over y^2}\right\}$}
@@ -245,25 +192,47 @@
% \ht\scratchbox-\scratchdimen
% \box\scratchbox}
-\def\math_cramped#1#2%
+% mkii:
+%
+% \def\math_cramped#1#2%
+% {\begingroup % added HH, made even more cramped
+% \setbox\scratchbox\hbox
+% {\nulldelimiterspace\zeropoint
+% \normalstartimath\mathsurround\zeropoint#1\radical\zerocount{#2}\normalstopimath}%
+% \ht\scratchbox-\dimexpr
+% \ifx#1\displaystyle
+% \fontdimen\pluseight\textfont\plusthree
+% +.25\fontdimen\plusfive\textfont\plustwo
+% \else
+% 1.25\fontdimen\pluseight
+% \ifx#1\textstyle
+% \textfont
+% \else\ifx#1\scriptstyle
+% \scriptfont
+% \else
+% \scriptscriptfont
+% \fi \fi
+% \plusthree
+% \fi
+% -\ht\scratchbox
+% \relax
+% \box\scratchbox
+% \endgroup}
+
+\def\math_cramped#1#2% we have all in one family
{\begingroup % added HH, made even more cramped
\setbox\scratchbox\hbox
{\nulldelimiterspace\zeropoint
\normalstartimath\mathsurround\zeropoint#1\radical\zerocount{#2}\normalstopimath}%
\ht\scratchbox-\dimexpr
\ifx#1\displaystyle
- \fontdimen8\textfont3
- +.25\fontdimen5\textfont2
+ \fontdimen\pluseight\textfont\plusone
+ + .25\fontdimen\plusfive \textfont\plusone
\else
- 1.25\fontdimen8
- \ifx#1\textstyle
- \textfont
- \else\ifx#1\scriptstyle
- \scriptfont
- \else
- \scriptscriptfont
- \fi \fi
- \plusthree
+ 1.25\fontdimen\pluseight
+ \ifx#1\textstyle \textfont \else
+ \ifx#1\scriptstyle\scriptfont \else
+ \scriptscriptfont\fi\fi \plusone
\fi
-\ht\scratchbox
\relax
@@ -305,7 +274,7 @@
% experiment, not yet to be used
-% \def\displaybreak
+% \unexpanded\def\displaybreak
% {\ifhmode
% \removeunwantedspaces
% \ifcase\raggedstatus\hfill\fi
diff --git a/tex/context/base/supp-ran.lua b/tex/context/base/supp-ran.lua
index 75202f696..7997db8f6 100644
--- a/tex/context/base/supp-ran.lua
+++ b/tex/context/base/supp-ran.lua
@@ -6,32 +6,34 @@ if not modules then modules = { } end modules ['supp-ran'] = {
license = "see context related readme files"
}
--- We cannot ask for the current seed, so we need some messy hack
--- here.
+-- We cannot ask for the current seed, so we need some messy hack here.
local report_system = logs.reporter("system","randomizer")
-commands = commands or { }
-local commands = commands
-
local math = math
+local context, commands = context, commands
+
local random, randomseed, round, seed, last = math.random, math.randomseed, math.round, false, 1
-function math.setrandomseedi(n,comment)
+local maxcount = 2^30-1 -- 1073741823
+
+local function setrandomseedi(n,comment)
if not n then
---~ n = 0.5 -- hack
+ -- n = 0.5 -- hack
end
if n <= 1 then
- n = n*1073741823 -- maxcount
+ n = n * maxcount
end
n = round(n)
if false then
report_system("setting seed to %s (%s)",n,comment or "normal")
end
randomseed(n)
- last = random(0,1073741823) -- we need an initial value
+ last = random(0,maxcount) -- we need an initial value
end
+math.setrandomseedi = setrandomseedi
+
function commands.getrandomcounta(min,max)
last = random(min,max)
context(last)
@@ -44,7 +46,7 @@ end
function commands.setrandomseed(n)
last = n
- math.setrandomseedi(n)
+ setrandomseedi(n)
end
function commands.getrandomseed(n)
@@ -54,10 +56,9 @@ end
-- maybe stack
function commands.freezerandomseed(n)
- -- print("<<<<",seed,last)
if seed == false or seed == nil then
seed = last
- math.setrandomseedi(seed,"freeze",seed)
+ setrandomseedi(seed,"freeze",seed)
end
if n then
randomseed(n)
@@ -65,9 +66,8 @@ function commands.freezerandomseed(n)
end
function commands.defrostrandomseed()
- -- print(">>>>",seed,last)
if seed ~= false then
- math.setrandomseedi(seed,"defrost",seed) -- was last (bug)
+ setrandomseedi(seed,"defrost",seed) -- was last (bug)
seed = false
end
end
diff --git a/tex/context/base/supp-ran.mkiv b/tex/context/base/supp-ran.mkiv
index 356ed580f..f5466a0e1 100644
--- a/tex/context/base/supp-ran.mkiv
+++ b/tex/context/base/supp-ran.mkiv
@@ -18,8 +18,8 @@
\registerctxluafile{supp-ran}{1.001}
-\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\getrandomcount #1#2#3{#1=\ctxcommand{getrandomcounta(\number#2,\number#3)}\relax}
+\unexpanded\def\getrandomdimen #1#2#3{#1=\ctxcommand{getrandomcounta(\number\dimexpr#2,\number\dimexpr#3)}\scaledpoint\relax}
\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)}}
diff --git a/tex/context/base/supp-vis.mkiv b/tex/context/base/supp-vis.mkiv
index 1b0253162..de7c4288d 100644
--- a/tex/context/base/supp-vis.mkiv
+++ b/tex/context/base/supp-vis.mkiv
@@ -96,8 +96,7 @@
%D off with \type{\dontinterfere}.
\unexpanded\def\dontinterfere % or maybe just forgetall
- {\everypar \emptytoks
- \let\par \endgraf
+ {\reseteverypar
\parindent\zeropoint
\parskip \zeropoint
\leftskip \zeropoint
@@ -186,12 +185,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\s!plus-1\s!fil\relax}
+\def\vfilneg {\normalvskip\zeropoint\s!plus-1\s!fil\relax}
+\def\hfillneg {\normalhskip\zeropoint\s!plus-1\s!fill\relax}
+\def\vfillneg {\normalvskip\zeropoint\s!plus-1\s!fill\relax}
+\def\hfilllneg{\normalhskip\zeropoint\s!plus-1\s!filll\relax}
+\def\vfilllneg{\normalvskip\zeropoint\s!plus-1\s!filll\relax}
%D \macros
%D {normalhss,normalhfil,normalhfill,
@@ -323,14 +322,14 @@
{\dontcomplain
\normaloffinterlineskip
\visualhrule
- \!!height\boxrulewidth
- \iftoprule\else\!!width\zeropoint\fi
+ \s!height\boxrulewidth
+ \iftoprule\else\s!width\zeropoint\fi
\normalvskip-\boxrulewidth
\normalhbox to \boxrulewd
{\visualvrule
- \!!height\boxruleht
- \!!depth \boxruledp
- \!!width \ifleftrule\boxrulewidth\else\zeropoint\fi
+ \s!height\boxruleht
+ \s!depth \boxruledp
+ \s!width \ifleftrule\boxrulewidth\else\zeropoint\fi
\ifdim\boxruleht>\zeropoint \else \baselinerulefalse \fi
\ifdim\boxruledp>\zeropoint \else \baselinerulefalse \fi
\ifbaselinerule
@@ -340,23 +339,23 @@
\cleaders
\ifbaselinefill
\visualhrule
- \!!height\boxrulewidth
+ \s!height\boxrulewidth
\else
\normalhbox
{\normalhskip2.5\boxrulewidth
\visualvrule
- \!!height\boxrulewidth
- \!!width5\boxrulewidth
+ \s!height\boxrulewidth
+ \s!width5\boxrulewidth
\normalhskip2.5\boxrulewidth}%
\fi
\fi
\normalhfill
\visualvrule
- \!!width\ifrightrule\boxrulewidth\else\zeropoint\fi}%
+ \s!width\ifrightrule\boxrulewidth\else\zeropoint\fi}%
\normalvskip-\boxrulewidth
\visualhrule
- \!!height\boxrulewidth
- \ifbottomrule\else\!!width\zeropoint\fi}%
+ \s!height\boxrulewidth
+ \ifbottomrule\else\s!width\zeropoint\fi}%
\wd#1\zeropoint
\setbox#1=\ifhbox#1\normalhbox\else\normalvbox\fi
{\normalhbox
@@ -726,9 +725,9 @@
\def\setvisiblehfilbox#1\to#2#3#4%
{\setbox#1\normalhbox
{\visualvrule
- \!!width #2\testrulewidth
- \!!height#3\testrulewidth
- \!!depth #4\testrulewidth}%
+ \s!width #2\testrulewidth
+ \s!height#3\testrulewidth
+ \s!depth #4\testrulewidth}%
\smashbox#1}
\def\doruledhfiller#1#2#3#4%
@@ -827,9 +826,9 @@
\def\setvisiblevfilbox#1\to#2#3#4%
{\setbox#1\normalhbox
{\visualvrule
- \!!width #2\testrulewidth
- \!!height#3\testrulewidth
- \!!depth #4\testrulewidth}%
+ \s!width #2\testrulewidth
+ \s!height#3\testrulewidth
+ \s!depth #4\testrulewidth}%
\smashbox#1}%
\def\doruledvfiller#1#2#3%
@@ -940,22 +939,22 @@
\setbox0\normalhbox
{\normalhskip-\testrulewidth
\visualvrule
- \!!width4\testrulewidth
- \!!height16\testrulewidth
- \!!depth16\testrulewidth}%
+ \s!width4\testrulewidth
+ \s!height16\testrulewidth
+ \s!depth16\testrulewidth}%
\else
\setbox0\normalhbox to \ifnegative-\fi\scratchskip
{\visualvrule
- \!!width2\testrulewidth
- \ifnegative\!!depth\else\!!height\fi16\testrulewidth
+ \s!width2\testrulewidth
+ \ifnegative\s!depth\else\s!height\fi16\testrulewidth
\cleaders
\visualhrule
\ifnegative
- \!!depth2\testrulewidth
- \!!height\zeropoint
+ \s!depth2\testrulewidth
+ \s!height\zeropoint
\else
- \!!height2\testrulewidth
- \!!depth\zeropoint
+ \s!height2\testrulewidth
+ \s!depth\zeropoint
\fi
\normalhfill
\ifflexible
@@ -965,15 +964,15 @@
\normalhbox
{\normalhskip 2\testrulewidth
\visualvrule
- \!!width2\testrulewidth
- \!!height\ifnegative-7\else9\fi\testrulewidth
- \!!depth\ifnegative9\else-7\fi\testrulewidth
+ \s!width2\testrulewidth
+ \s!height\ifnegative-7\else9\fi\testrulewidth
+ \s!depth\ifnegative9\else-7\fi\testrulewidth
\normalhskip 2\testrulewidth}%
\normalhfill
\fi
\visualvrule
- \!!width2\testrulewidth
- \ifnegative\!!depth\else\!!height\fi16\testrulewidth}%
+ \s!width2\testrulewidth
+ \ifnegative\s!depth\else\s!height\fi16\testrulewidth}%
\setbox0\normalhbox
{\ifnegative\else\normalhskip-\scratchskip\fi
\box0}%
@@ -1076,14 +1075,14 @@
\ifzero
\setbox0\normalvcue
{\visualvrule
- \!!width32\testrulewidth
- \!!height2\testrulewidth
- \!!depth2\testrulewidth}%
+ \s!width32\testrulewidth
+ \s!height2\testrulewidth
+ \s!depth2\testrulewidth}%
\else
\setbox0\normalvbox to \ifnegative-\fi\scratchskip
{\visualhrule
- \!!width16\testrulewidth
- \!!height2\testrulewidth
+ \s!width16\testrulewidth
+ \s!height2\testrulewidth
\ifflexible
\cleaders
\normalhbox to 16\testrulewidth
@@ -1091,8 +1090,8 @@
\normalvbox
{\normalvskip 2\testrulewidth
\visualhrule
- \!!width2\testrulewidth
- \!!height2\testrulewidth
+ \s!width2\testrulewidth
+ \s!height2\testrulewidth
\normalvskip 2\testrulewidth}%
\normalhss}%
\normalvfill
@@ -1100,12 +1099,12 @@
\normalvfill
\fi
\visualhrule
- \!!width16\testrulewidth
- \!!height2\testrulewidth}%
+ \s!width16\testrulewidth
+ \s!height2\testrulewidth}%
\setbox2\normalvbox to \ht0
{\visualhrule
- \!!width2\testrulewidth
- \!!height\ht0}%
+ \s!width2\testrulewidth
+ \s!height\ht0}%
\ifnegative
\ht0\zeropoint
\setbox0\normalhbox
@@ -1192,25 +1191,25 @@
\ifzero
\setbox0\ruledhbox to 8\testrulewidth
{\visualvrule
- \!!width\zeropoint
- \!!height16\testrulewidth
- \!!depth16\testrulewidth}%
+ \s!width\zeropoint
+ \s!height16\testrulewidth
+ \s!depth16\testrulewidth}%
\setbox0\normalhbox
{\normalhskip-4\testrulewidth\box0}%
\else
\setbox0\ruledhbox to \ifnegative-\fi\scratchskip
{\visualvrule
- \!!width\zeropoint
- \ifnegative\!!depth\else\!!height\fi16\testrulewidth
+ \s!width\zeropoint
+ \ifnegative\s!depth\else\s!height\fi16\testrulewidth
\ifflexible
\normalhskip2\testrulewidth
\cleaders
\normalhbox
{\normalhskip 2\testrulewidth
\visualvrule
- \!!width2\testrulewidth
- \!!height\ifnegative-7\else9\fi\testrulewidth
- \!!depth\ifnegative9\else-7\fi\testrulewidth
+ \s!width2\testrulewidth
+ \s!height\ifnegative-7\else9\fi\testrulewidth
+ \s!depth\ifnegative9\else-7\fi\testrulewidth
\normalhskip 2\testrulewidth}%
\normalhfill
\else
@@ -1268,9 +1267,9 @@
\ifzero
\setbox0\ruledhbox to 32\testrulewidth
{\visualvrule
- \!!width\zeropoint
- \!!height4\testrulewidth
- \!!depth4\testrulewidth}%
+ \s!width\zeropoint
+ \s!height4\testrulewidth
+ \s!depth4\testrulewidth}%
\else
\setbox0\ruledvbox to \ifnegative-\fi\scratchskip
{\hsize16\testrulewidth
@@ -1281,15 +1280,15 @@
\normalvbox
{\normalvskip 2\testrulewidth
\visualhrule
- \!!width2\testrulewidth
- \!!height2\testrulewidth
+ \s!width2\testrulewidth
+ \s!height2\testrulewidth
\normalvskip 2\testrulewidth}%
\normalhss}%
\normalvfill
\else
\visualvrule
- \!!width\zeropoint
- \!!height\ifnegative-\fi\scratchskip
+ \s!width\zeropoint
+ \s!height\ifnegative-\fi\scratchskip
\normalhfill
\fi}
\fi
@@ -1363,7 +1362,7 @@
\def\supp_visualizers_hglue_indeed
{\leavevmode
\scratchcounter\spacefactor
- \visualvrule\!!width\zeropoint
+ \visualvrule\s!width\zeropoint
\normalpenalty\plustenthousand
\ruledhkern\normalhskip\scratchskip
\spacefactor\scratchcounter
@@ -1393,7 +1392,7 @@
\def\supp_visualizers_vglue_indeed
{\endgraf % \par
\nextdepth\prevdepth
- \visualhrule\!!height\zeropoint
+ \visualhrule\s!height\zeropoint
\normalpenalty\plustenthousand
\ruledvkern\normalvskip\scratchskip
\prevdepth\nextdepth
@@ -1419,26 +1418,26 @@
{$\normalmkern\ifnegative-\fi\scratchskip$}%
\setbox\boxrulescratchbox\normalhbox to \wd\boxrulescratchbox
{\visualvrule
- \!!height16\testrulewidth
- \!!depth 16\testrulewidth
- \!!width \testrulewidth
+ \s!height16\testrulewidth
+ \s!depth 16\testrulewidth
+ \s!width \testrulewidth
\leaders
\visualhrule
- \!!height\ifpositive 16\else-14\fi\testrulewidth
- \!!depth \ifpositive-14\else 16\fi\testrulewidth
+ \s!height\ifpositive 16\else-14\fi\testrulewidth
+ \s!depth \ifpositive-14\else 16\fi\testrulewidth
\normalhfill
\ifflexible
\normalhskip-\wd\boxrulescratchbox
\leaders
\visualhrule
- \!!height\testrulewidth
- \!!depth \testrulewidth
+ \s!height\testrulewidth
+ \s!depth \testrulewidth
\normalhfill
\fi
\visualvrule
- \!!height16\testrulewidth
- \!!depth 16\testrulewidth
- \!!width \testrulewidth}%
+ \s!height16\testrulewidth
+ \s!depth 16\testrulewidth
+ \s!width \testrulewidth}%
\smashbox0%
\ifnegative
#1\scratchskip
@@ -1569,19 +1568,19 @@
\normalhskip-\scratchdimen
\normalhskip-2\testrulewidth
\visualvrule
- \!!width 2\testrulewidth
- \!!height#3\testrulewidth
- \!!depth #4\testrulewidth
+ \s!width 2\testrulewidth
+ \s!height#3\testrulewidth
+ \s!depth #4\testrulewidth
\fi
\visualvrule
- \!!width \scratchdimen
- \!!height#5\testrulewidth
- \!!depth #6\testrulewidth
+ \s!width \scratchdimen
+ \s!height#5\testrulewidth
+ \s!depth #6\testrulewidth
\ifnum#2>\zerocount
\visualvrule
- \!!width 2\testrulewidth
- \!!height#3\testrulewidth
- \!!depth #4\testrulewidth
+ \s!width 2\testrulewidth
+ \s!height#3\testrulewidth
+ \s!depth #4\testrulewidth
\fi
\fi}%
\smashbox#1}
@@ -1600,8 +1599,8 @@
\setbox0\ruledhbox to 8\testrulewidth
{\ifnegative\else\normalhss\fi
\visualvrule
- \!!depth8\testrulewidth
- \!!width\ifzero\zeropoint\else4\testrulewidth\fi
+ \s!depth8\testrulewidth
+ \s!width\ifzero\zeropoint\else4\testrulewidth\fi
\ifpositive\else\normalhss\fi}%
\supp_visualizers_penalty_box{2}{\scratchcounter}{0}{8}{-3.5}{4.5}%
\normalpenalty\plustenthousand
@@ -1651,13 +1650,13 @@
\boxrulewidth\testrulewidth
\setbox0\ruledhbox
{\visualvrule
- \!!height4\testrulewidth
- \!!depth 4\testrulewidth
- \!!width \zeropoint
+ \s!height4\testrulewidth
+ \s!depth 4\testrulewidth
+ \s!width \zeropoint
\visualvrule
- \!!height\ifnegative.5\else4\fi\testrulewidth
+ \s!height\ifnegative.5\else4\fi\testrulewidth
\!!dept \ifpositive.5\else4\fi\testrulewidth
- \!!width 8\testrulewidth}%
+ \s!width 8\testrulewidth}%
\supp_visualizers_penalty_box{2}{\scratchcounter}{4}{4}{.5}{.5}%
\setbox0\normalhbox
{\normalhskip-4\testrulewidth
diff --git a/tex/context/base/symb-run.mkiv b/tex/context/base/symb-run.mkiv
index 4bd2cecca..3d92c4416 100644
--- a/tex/context/base/symb-run.mkiv
+++ b/tex/context/base/symb-run.mkiv
@@ -44,10 +44,10 @@
\unprotect
-\gdef\doshowsymbolset[#1]%
- {\ctxcommand{showsymbolset("#1","\symbolset{#1}")}}
+\unexpanded\gdef\showsymbolset
+ {\dosingleargument\symb_show_set}
-\gdef\showsymbolset
- {\dosingleargument\doshowsymbolset}
+\gdef\symb_show_set[#1]%
+ {\ctxcommand{showsymbolset("#1","\symbolset{#1}")}}
\protect \endinput
diff --git a/tex/context/base/syst-aux.lua b/tex/context/base/syst-aux.lua
index 7fd25d6ab..cda340cb6 100644
--- a/tex/context/base/syst-aux.lua
+++ b/tex/context/base/syst-aux.lua
@@ -6,19 +6,37 @@ if not modules then modules = { } end modules ['syst-aux'] = {
license = "see context related readme files"
}
+-- slower than lpeg:
+--
+-- utfmatch(str,"(.?)(.*)$")
+-- utf.sub(str,1,1)
+
+local commands, context = commands, context
+
local settings_to_array = utilities.parsers.settings_to_array
local concat = table.concat
+local format = string.format
+local utfsub = utf.sub
+local P, C, Carg, lpegmatch, utf8char = lpeg.P, lpeg.C, lpeg.Carg, lpeg.match, lpeg.patterns.utf8char
local setvalue = context.setvalue
+local pattern = C(utf8char^-1) * C(P(1)^0)
+
function commands.getfirstcharacter(str)
- local first, rest = utf.match(str,"(.?)(.*)$")
+ local first, rest = lpegmatch(pattern,str)
setvalue("firstcharacter",first)
setvalue("remainingcharacters",rest)
end
+local pattern = C(utf8char^-1)
+
function commands.doiffirstcharelse(chr,str)
- commands.doifelse(utf.sub(str,1,1) == chr)
+ commands.doifelse(lpegmatch(pattern,str) == chr)
+end
+
+function commands.getsubstring(str,first,last)
+ context(utfsub(str,tonumber(first),tonumber(last)))
end
-- function commands.addtocommalist(list,item)
@@ -50,3 +68,14 @@ end
-- end
-- end
-- end
+
+local pattern = (C((1-P("%"))^1) * Carg(1)) /function(n,d) return format("%.0fsp",d * tonumber(n)/100) end * P("%") * P(-1)
+
+-- commands.percentageof("10%",65536*10)
+
+function commands.percentageof(str,dim)
+ context(lpegmatch(pattern,str,1,dim) or str)
+end
+
+-- \gdef\setpercentdimen#1#2%
+-- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax}
diff --git a/tex/context/base/syst-aux.mkiv b/tex/context/base/syst-aux.mkiv
index 0e43a6202..058a251cb 100644
--- a/tex/context/base/syst-aux.mkiv
+++ b/tex/context/base/syst-aux.mkiv
@@ -11,10 +11,6 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%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
@@ -38,13 +34,13 @@
%D is used in \CONTEXT\ and therefore we might also assume that
%D some basic functionality is available.
%D
-%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.
+%D Some of the macros here were only used in the bibliography module. They
+%D have been be moved to a separate syst module since the bib module is no
+%D longer using them. Some more will go away.
+
\unprotect
%D \macros
@@ -62,6 +58,21 @@
\let\unexpanded\normalprotected
+%D As we don't have namespace definers yet, we use a special one:
+
+\newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes
+
+\def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>}
+%def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet
+
+\unexpanded\def\installsystemnamespace#1% maybe move this to syst-ini
+ {\ifcsname ??#1\endcsname
+ \writestatus\m!system{duplicate system namespace '#1'}\wait
+ \else
+ \global\advance\c_syst_helpers_n_of_namespaces\plusone
+ \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}%
+ \fi}
+
%D \macros
%D {normalspace}
%D
@@ -150,34 +161,35 @@
\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
-%D be enclosed with \type{\expanded}, like:
+%D Sometimes we pass macros as arguments to commands that don't expand them
+%D before interpretation. Such commands can be enclosed with \type {\expanded},
+%D like:
%D
%D \starttyping
%D \expanded{\setupsomething[\alfa]}
%D \stoptyping
%D
-%D Such situations occur for instance when \type{\alfa} is a
-%D commalist or when data stored in macros is fed to index of
-%D list commands. If needed, one should use \type{\noexpand}
-%D inside the argument. Later on we will meet some more clever
-%D alternatives to this command. Beware, only the simple one
-%D has \type {\noexpand} before its argument.
+%D Such situations occur for instance when \type{\alfa} is a commalist or when data
+%D stored in macros is fed to index of list commands. If needed, one should use
+%D \type{\noexpand} inside the argument. Later on we will meet some more clever
+%D alternatives to this command. Beware, only the simple one has \type {\noexpand}
+%D before its argument.
-\let\@@expanded\empty % always long and global (less restores)
+\let\m_syst_helpers_expanded\empty
\unexpanded\def\expanded#1%
- {\xdef\@@expanded{\noexpand#1}\@@expanded}
+ {\xdef\m_syst_helpers_expanded{\noexpand#1}\m_syst_helpers_expanded}
-\unexpanded\def\startexpanded#1\stopexpanded % see x-fo for example
- {\xdef\@@expanded{#1}\@@expanded}
+\unexpanded\def\startexpanded#1\stopexpanded
+ {\xdef\m_syst_helpers_expanded{#1}\m_syst_helpers_expanded}
\let\stopexpanded\relax
-%D Recent \TEX's have a primitive \expanded
+%D Recent \TEX\ engines have a primitive \type {\expanded} and we will use that when
+%D possible. After all, we can make not expandable macros now.
-% not yet as we need to adapt ##'s in calls
+% We cannot use the next variant as first we need to adapt \type {##}'s
+% in callers:
%
% \def\expanded#1%
% {\normalexpanded{\noexpand#1}}
@@ -188,8 +200,8 @@
%D \macros
%D {gobbleoneargument,gobble...arguments}
%D
-%D The next set of macros just do nothing, except that they
-%D get rid of a number of arguments.
+%D The next set of macros just do nothing, except that they get rid of a number of
+%D arguments.
\def\gobbleoneargument #1{}
\def\gobbletwoarguments #1#2{}
@@ -208,6 +220,18 @@
\def\gobblefouroptionals [#1][#2][#3][#4]{}
\def\gobblefiveoptionals [#1][#2][#3][#4][#5]{}
+%D Reserved macros for tests:
+
+\let\donothing\empty
+
+\let\m_syst_string_one \empty
+\let\m_syst_string_two \empty
+\let\m_syst_string_three\empty
+\let\m_syst_string_four \empty
+
+\let\m_syst_action_yes \empty
+\let\m_syst_action_nop \empty
+
%D \macros
%D {doifnextcharelse}
%D
@@ -235,8 +259,8 @@
\unexpanded\def\doifnextcharelse#1#2#3% #1 should not be {} !
{\let\charactertoken=#1% = needed here
- \def\!!stringa{#2}%
- \def\!!stringb{#3}%
+ \def\m_syst_action_yes{#2}%
+ \def\m_syst_action_nop{#3}%
\futurelet\nexttoken\syst_helpers_inspect_next_character}
\def\syst_helpers_inspect_next_character
@@ -248,9 +272,9 @@
\def\syst_helpers_inspect_next_character_indeed
{\ifx\nexttoken\charactertoken
- \expandafter\!!stringa
+ \expandafter\m_syst_action_yes
\else
- \expandafter\!!stringb
+ \expandafter\m_syst_action_nop
\fi}
%D Because we will mostly use this macro for testing if the next
@@ -274,14 +298,14 @@
\let\syst_helpers_next_optional_character_token=[
\unexpanded\def\doifnextoptionalelse#1#2%
- {\def\syst_helpers_next_optional_command_yes{#1}%
- \def\syst_helpers_next_optional_command_nop{#2}%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
\let\if_next_blank_space_token\iffalse
\futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
\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\m_syst_action_yes#1%
+ \let\m_syst_action_nop#2%
\let\if_next_blank_space_token\iffalse
\futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
@@ -294,16 +318,16 @@
\def\syst_helpers_inspect_next_optional_character_indeed
{\ifx\nexttoken\syst_helpers_next_optional_character_token
- \expandafter\syst_helpers_next_optional_command_yes
+ \expandafter\m_syst_action_yes
\else
- \expandafter\syst_helpers_next_optional_command_nop
+ \expandafter\m_syst_action_nop
\fi}
\let\syst_helpers_next_bgroup_character_token\bgroup
\unexpanded\def\doifnextbgroupelse#1#2%
- {\def\syst_helpers_next_bgroup_command_yes{#1}%
- \def\syst_helpers_next_bgroup_command_nop{#2}%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
\let\if_next_blank_space_token\iffalse
\futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
@@ -316,16 +340,16 @@
\def\syst_helpers_inspect_next_bgroup_character_indeed
{\ifx\nexttoken\syst_helpers_next_bgroup_character_token
- \expandafter\syst_helpers_next_bgroup_command_yes
+ \expandafter\m_syst_action_yes
\else
- \expandafter\syst_helpers_next_bgroup_command_nop
+ \expandafter\m_syst_action_nop
\fi}
\let\syst_helpers_next_parenthesis_character_token(
\unexpanded\def\doifnextparenthesiselse#1#2%
- {\def\syst_helpers_next_parenthesis_command_yes{#1}%
- \def\syst_helpers_next_parenthesis_command_nop{#2}%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_nop{#2}%
\let\if_next_blank_space_token\iffalse
\futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
@@ -338,44 +362,39 @@
\def\syst_helpers_inspect_next_parenthesis_character_indeed
{\ifx\nexttoken\syst_helpers_next_parenthesis_character_token
- \expandafter\syst_helpers_next_parenthesis_command_yes
+ \expandafter\m_syst_action_yes
\else
- \expandafter\syst_helpers_next_parenthesis_command_nop
+ \expandafter\m_syst_action_nop
\fi}
%D The next one is handy in predictable situations:
\unexpanded\def\doiffastoptionalcheckelse#1#2%
- {\def\syst_helpers_next_optional_command_yes{#1}%
- \def\syst_helpers_next_optional_command_nop{#2}%
+ {\def\m_syst_action_yes{#1}%
+ \def\m_syst_action_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%
+ {\let\m_syst_action_yes#1%
+ \let\m_syst_action_nop#2%
\futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
\def\syst_helpers_do_if_fast_optional_check_else
{\ifx\nexttoken\syst_helpers_next_optional_character_token
- \expandafter\syst_helpers_next_optional_command_yes
+ \expandafter\m_syst_action_yes
\else
- \expandafter\syst_helpers_next_optional_command_nop
+ \expandafter\m_syst_action_nop
\fi}
-%D This macro uses some auxiliary macros. Although we were able
-%D to program quite complicated things, I only understood these
-%D after rereading the \TEX book. The trick is in using a
-%D command with a one character name. Such commands differ from
-%D the longer ones in the fact that trailing spaces are {\em
-%D not} skipped. This enables us to indirectly define a long
-%D named macro that gobbles a space.
-%D
-%D In the first line we define \type{\blankspace}. Next we
-%D make \type{\:} equivalent to \type{\reinspect...}. This
-%D one||character command is expanded before the next
-%D \type{\def} comes into action. This way the space after
-%D \type{\:} becomes a delimiter of the longer named
-%D \type{\reinspectnextcharacter}.
+%D This macro uses some auxiliary macros. Although we were able to program quite
+%D complicated things, I only understood these after rereading the \TEX book. The
+%D trick is in using a command with a one character name. Such commands differ from
+%D the longer ones in the fact that trailing spaces are {\em not} skipped. This
+%D enables us to indirectly define a long named macro that gobbles a space. In the
+%D first line we define \type {\blankspace}. Next we make \type {\:} equivalent to
+%D \type {\reinspect...}. This one||character command is expanded before the next
+%D \type {\def} comes into action. This way the space after \type {\:} becomes a
+%D delimiter of the longer named \type {\reinspectnextcharacter}.
% try: \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character} {...}
@@ -402,10 +421,9 @@
%D letvalue,letgvalue,getvalue,resetvalue,
%D undefinevalue,ignorevalue}
%D
-%D \TEX's primitive \type{\csname} can be used to construct
-%D all kind of commands that cannot be defined with
-%D \type{\def} and \type{\let}. Every macro programmer sooner
-%D or later wants macros like these.
+%D \TEX's primitive \type {\csname} can be used to construct all kind of commands
+%D that cannot be defined with \type {\def} and \type {\let}. Every macro programmer
+%D sooner or later wants macros like these.
%D
%D \starttyping
%D \setvalue {name}{...} = \def\name{...}
@@ -418,9 +436,8 @@
%D \resetvalue {name} = \def\name{}
%D \stoptyping
%D
-%D As we will see, \CONTEXT\ uses these commands many times,
-%D which is mainly due to its object oriented and parameter
-%D driven character.
+%D As we will see, \CONTEXT\ uses these commands many times, which is mainly due to
+%D its object oriented and parameter driven character.
\def\setvalue #1{\expandafter \def\csname#1\endcsname}
\def\setgvalue #1{\expandafter\gdef\csname#1\endcsname}
@@ -441,22 +458,20 @@
%D \macros
%D {globallet,glet}
%D
-%D In \CONTEXT\ of May 2000 using \type {\globallet}
-%D instead of the two tokens will save us some
-%D $300\times4=1200$ bytes of format file on a 32~bit
-%D system. So:
+%D In \CONTEXT\ of May 2000 using \type {\globallet} instead of the two
+%D tokens will save us some $300\times4=1200$ bytes of format file on a 32~bit
+%D system. Not that it matters much today. This shortcut is already defined:
-\def\globallet{\global\let} \let\glet\globallet
+\unexpanded\def\glet{\global\let} \let\globallet\glet
%D \macros
%D {doifundefined,doifdefined,
%D doifundefinedelse,doifdefinedelse,
%D doifalldefinedelse}
%D
-%D The standard way of testing if a macro is defined is
-%D comparing its meaning with another undefined one, usually
-%D \type{\undefined}. To garantee correct working of the next
-%D set of macros, \type{\undefined} may never be defined!
+%D The standard way of testing if a macro is defined is comparing its meaning with
+%D another undefined one, usually \type{\undefined}. To garantee correct working of
+%D the next set of macros, \type{\undefined} may never be defined!
%D
%D \starttyping
%D \doifundefined {string} {...}
@@ -466,13 +481,12 @@
%D \doifalldefinedelse {commalist} {then ...} {else ...}
%D \stoptyping
%D
-%D Every macroname that \TEX\ builds gets an entry in the hash
-%D table, which is of limited size. It is expected that e-\TeX\
-%D will offer a less memory||consuming alternative.
+%D Every macroname that \TEX\ builds gets an entry in the hash table, which is of
+%D limited size. It is expected that \ETEX\ will offer a less memory||consuming
+%D alternative.
-%D Although it will probably never be a big problem, it is good
-%D to be aware of the difference between testing on a macro
-%D name to be build by using \type{\csname} and
+%D Although it will probably never be a big problem, it is good to be aware of the
+%D difference between testing on a macro name to be build by using \type{\csname} and
%D \type{\endcsname} and testing the \type{\name} directly.
%D
%D \starttyping
@@ -481,11 +495,6 @@
%D \ifundefined\NameB ... \else ... \fi
%D \stoptyping
-% \def\ifundefined#1% obsolete
-% {\unless\ifcsname#1\endcsname}
-%
-% use a real if like \ifcsname#1\endcsname\else instead
-
\suppressifcsnameerror\plusone
\def\doifundefinedelse#1%
@@ -511,12 +520,10 @@
%D \macros
%D {letbeundefined}
%D
-%D Testing for being undefined comes down to testing on \type
-%D {\relax} when we use \type {\csname}, but when using \type
-%D {\ifx}, we test on being \type {\undefined}! In \ETEX\ we
-%D have \type {\ifcsname} and that way of testing on existance
-%D is not the same as the one described here. Therefore we
-%D introduce:
+%D Testing for being undefined comes down to testing on \type {\relax} when we use
+%D \type {\csname}, but when using \type {\ifx}, we test on being \type
+%D {\undefined}! In \ETEX\ we have \type {\ifcsname} and that way of testing on
+%D existance is not the same as the one described here. Therefore we introduce:
\def\letbeundefined#1% potential stack buildup when used \global
{\expandafter\let\csname#1\endcsname\undefined}
@@ -527,13 +534,11 @@
\def\globalundefine#1% conditional
{\ifcsname#1\endcsname\expandafter\global\let\csname#1\endcsname\undefined\fi}
-%D Beware, being \type {\undefined} in \ETEX\ means that the macro
-%D {\em is} defined!
-
-%D When we were developing the scientific units module, we
-%D encountered different behavior in text and math mode, which
-%D was due to this grouping subtilities. We therefore decided
-%D to use \type{\begingroup} instead of \type{\bgroup}.
+%D Beware, being \type {\undefined} in \ETEX\ means that the macro {\em is} defined!
+%D
+%D When we were developing the scientific units module, we encountered different
+%D behavior in text and math mode, which was due to this grouping subtilities. We
+%D therefore decided to use \type{\begingroup} instead of \type{\bgroup}.
\unexpanded\def\doifalldefinedelse#1%
{\begingroup
@@ -554,15 +559,13 @@
%D \macros
%D {doif,doifelse,doifnot}
%D
-%D Programming in \TEX\ differs from programming in procedural
-%D languages like \MODULA. This means that one --- well, let me
-%D speek for myself --- tries to do the things in the well
-%D known way. Therefore the next set of \type{\ifthenelse}
-%D commands were between the first ones we needed. A few years
-%D later, the opposite became true: when programming in
-%D \MODULA, I sometimes miss handy things like grouping,
-%D runtime redefinition, expansion etc. While \MODULA\ taught
-%D me to structure, \TEX\ taught me to think recursive.
+%D Programming in \TEX\ differs from programming in procedural languages like
+%D \MODULA. This means that one --- well, let me speek for myself --- tries to do
+%D the things in the well known way. Therefore the next set of \type{\ifthenelse}
+%D commands were between the first ones we needed. A few years later, the opposite
+%D became true: when programming in \MODULA, I sometimes miss handy things like
+%D grouping, runtime redefinition, expansion etc. While \MODULA\ taught me to
+%D structure, \TEX\ taught me to think recursive.
%D
%D \starttyping
%D \doif {string1} {string2} {...}
@@ -571,27 +574,27 @@
%D \stoptyping
\unexpanded\def\doif#1#2%
- {\edef\!!stringa{#1}%
- \edef\!!stringb{#2}%
- \ifx\!!stringa\!!stringb
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
\unexpanded\def\doifnot#1#2%
- {\edef\!!stringa{#1}%
- \edef\!!stringb{#2}%
- \ifx\!!stringa\!!stringb
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
\unexpanded\def\doifelse#1#2%
- {\edef\!!stringa{#1}%
- \edef\!!stringb{#2}%
- \ifx\!!stringa\!!stringb
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
@@ -611,24 +614,24 @@
%D This time, the string is not expanded.
\unexpanded\def\doifemptyelse#1%
- {\def\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
\unexpanded\def\doifempty#1%
- {\def\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
\unexpanded\def\doifnotempty#1%
- {\def\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\def\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
@@ -637,9 +640,8 @@
%D \macros
%D {doifinset,doifnotinset,doifinsetelse}
%D
-%D We can check if a string is present in a comma separated
-%D set of strings. Depending on the result, some action is
-%D taken.
+%D We can check if a string is present in a comma separated set of strings.
+%D Depending on the result, some action is taken.
%D
%D \starttyping
%D \doifinset {string} {string,...} {...}
@@ -680,119 +682,119 @@
\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}
-\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}
+\def\syst_helpers_re_do_if_in_set_else{\expandafter\syst_helpers_do_check_if_item_in_set_else\m_syst_string_two,],\relax}
+\def\syst_helpers_re_do_if_in_set {\expandafter\syst_helpers_do_check_if_item_in_set \m_syst_string_two,],\relax}
+\def\syst_helpers_re_do_if_not_in_set {\expandafter\syst_helpers_do_check_if_item_not_in_set \m_syst_string_two,],\relax}
\unexpanded\def\doifinsetelse#1% make this two step too
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\thirdofthreearguments
\else
\expandafter\syst_helpers_do_if_in_set_else
\fi}
\def\syst_helpers_do_if_in_set_else#1%
- {\edef\!!stringb{#1}%
- \ifx\!!stringb\empty
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\empty
\expandafter\secondoftwoarguments
\else
\expandafter\syst_helpers_re_do_if_in_set_else
\fi}
\unexpanded\def\doifinset#1%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\gobbletwoarguments
\else
\expandafter\syst_helpers_do_if_in_set
\fi}
\def\syst_helpers_do_if_in_set#1%
- {\edef\!!stringb{#1}%
- \ifx\!!stringb\empty
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\empty
\expandafter\gobbleoneargument
\else
\expandafter\syst_helpers_re_do_if_in_set
\fi}
\unexpanded\def\doifnotinset#1%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\secondoftwoarguments
\else
\expandafter\syst_helpers_do_if_not_in_set
\fi}
\def\syst_helpers_do_if_not_in_set#1%
- {\edef\!!stringb{#1}%
- \ifx\!!stringb\empty
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\empty
\expandafter\firstofoneargument
\else
\expandafter\syst_helpers_re_do_if_not_in_set % ...]{true}
\fi}
\def\syst_helpers_do_check_if_item_in_set_else#1,#2% #2 eats up preceding space
- {\edef\!!stringb{#1}%
- \ifx\!!stringb\empty
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\empty
\expandafter\syst_helpers_do_check_if_item_in_set_else
\else
\expandafter\syst_helpers_do_do_check_if_item_in_set_else
\fi#2}
\def\syst_helpers_do_do_check_if_item_in_set_else
- {\ifx\!!stringb\v_syst_helpers_right_optional_bracket
+ {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
\expandafter\thirdofthreearguments
\else
\expandafter\syst_helpers_do_do_do_check_if_item_in_set_else
\fi}
\def\syst_helpers_do_do_do_check_if_item_in_set_else
- {\ifx\!!stringa\!!stringb
+ {\ifx\m_syst_string_one\m_syst_string_two
\expandafter\syst_helpers_do_quit_if_item_in_set_else
\else
\expandafter\syst_helpers_do_check_if_item_in_set_else
\fi}
\def\syst_helpers_do_check_if_item_in_set#1,#2% #2 eats up preceding space
- {\edef\!!stringb{#1}%
- \ifx\!!stringb\empty
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\empty
\expandafter\syst_helpers_do_check_if_item_in_set
\else
\expandafter\syst_helpers_do_do_check_if_item_in_set
\fi#2}
\def\syst_helpers_do_do_check_if_item_in_set
- {\ifx\!!stringb\v_syst_helpers_right_optional_bracket
+ {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
\expandafter\gobbletwoarguments
\else
\expandafter\syst_helpers_do_do_do_check_if_item_in_set
\fi}
\def\syst_helpers_do_do_do_check_if_item_in_set
- {\ifx\!!stringa\!!stringb
+ {\ifx\m_syst_string_one\m_syst_string_two
\expandafter\syst_helpers_do_quit_if_item_in_set
\else
\expandafter\syst_helpers_do_check_if_item_in_set
\fi}
\def\syst_helpers_do_check_if_item_not_in_set#1,#2% #2 eats up preceding space
- {\edef\!!stringb{#1}%
- \ifx\!!stringb\empty
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\empty
\expandafter\syst_helpers_do_check_if_item_not_in_set
\else
\expandafter\syst_helpers_do_do_check_if_item_not_in_set
\fi#2}
\def\syst_helpers_do_do_check_if_item_not_in_set
- {\ifx\!!stringb\v_syst_helpers_right_optional_bracket
+ {\ifx\m_syst_string_two\v_syst_helpers_right_optional_bracket
\expandafter\secondoftwoarguments
\else
\expandafter\syst_helpers_do_do_do_check_if_item_not_in_set
\fi}
\def\syst_helpers_do_do_do_check_if_item_not_in_set
- {\ifx\!!stringa\!!stringb
+ {\ifx\m_syst_string_one\m_syst_string_two
\expandafter\syst_helpers_do_quit_if_item_not_in_set
\else
\expandafter\syst_helpers_do_check_if_item_not_in_set
@@ -801,8 +803,8 @@
%D \macros
%D {doifcommon,doifnotcommon,doifcommonelse}
%D
-%D Probably the most time consuming tests are those that test
-%D for overlap in sets of strings.
+%D Probably the most time consuming tests are those that test for overlap in sets
+%D of strings.
%D
%D \starttyping
%D \doifcommon {string,...} {string,...} {...}
@@ -890,16 +892,16 @@
%D {processcommalist,processcommacommand,quitcommalist,
%D processcommalistwithparameters}
%D
-%D We've already seen some macros that take care of comma
-%D separated lists. Such list can be processed with
+%D We've already seen some macros that take care of comma separated lists. Such
+%D list can be processed with
%D
%D \starttyping
%D \processcommalist[string,string,...]\commando
%D \stoptyping
%D
-%D The user supplied command \type{\commando} receives one
-%D argument: the string. This command permits nesting and
-%D spaces after commas are skipped. Empty sets are no problem.
+%D The user supplied command \type{\commando} receives one argument: the string.
+%D This command permits nesting and spaces after commas are skipped. Empty sets
+%D are no problem.
%D
%D \startbuffer
%D \def\dosomething#1{(#1)}
@@ -920,8 +922,10 @@
\newcount\commalevel
+\installsystemnamespace{nextcommalevel}
+
\def\syst_helpers_do_do_do_process_comma_item
- {\csname\s!next\the\commalevel\endcsname}
+ {\csname\??nextcommalevel\the\commalevel\endcsname}
\def\syst_helpers_do_do_process_comma_item
{\ifx\nexttoken\blankspace
@@ -940,9 +944,8 @@
\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}]}.
+%D Empty arguments are not processed. Empty items (\type {,,}) however are
+%D treated. We have to check for the special case \type {[{a,b,c}]}.
\unexpanded\def\processcommalist[%
{\futurelet\nexttoken\syst_helpers_do_check_comma_item}
@@ -957,27 +960,27 @@
\def\syst_helpers_do_process_comma_list#1]#2%
{\global\advance\commalevel \plusone
- \expandafter\def\csname\s!next\the\commalevel\endcsname##1,%
+ \expandafter\def\csname\??nextcommalevel\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
+\unexpanded\def\quitcommalist
{\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list}
\def\syst_helpers_do_quit_comma_list#1]%
{\endgroup}
-\def\quitprevcommalist
+\unexpanded\def\quitprevcommalist
{\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_prev_comma_list}
\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.
+%D The hack we used for checking the next character \type {\doifnextcharelse}
+%D is also used here.
\let\next\:
@@ -991,15 +994,13 @@
%D
%D \getbuffer
-%D When a list is saved in a macro, we can use a construction
-%D like:
+%D When a list is saved in a macro, we can use a construction like:
%D
%D \starttyping
%D \expandafter\processcommalist\expandafter[\list]\command
%D \stoptyping
%D
-%D Such solutions suit most situations, but we wanted a bit
-%D more.
+%D Such solutions suit most situations, but we wanted a bit more.
%D
%D \starttyping
%D \processcommacommand[string,\stringset,string]\commando
@@ -1016,14 +1017,14 @@
%D \processcommacommand[\first,between,\second]\message
%D \stoptyping
%D
-%D Commands that are part of the list are expanded, so the
-%D use of this macro has its limits.
+%D Commands that are part of the list are expanded, so the use of
+%D this macro has its limits.
\unexpanded\def\processcommacommand[#1]%
{\normalexpanded{\processcommalist[#1]}}
-%D The argument to \type{\command} is not delimited. Because
-%D we often use \type{[]} as delimiters, we also have:
+%D The argument to \type{\command} is not delimited. Because we often
+%D use \type{[]} as delimiters, we also have:
%D
%D \starttyping
%D \processcommalistwithparameters[string,string,...]\command
@@ -1044,13 +1045,18 @@
%D
%D Two more:
+\let\syst_helpers_comma_list_step\relax
+
\unexpanded\def\startprocesscommalist[#1]#2\stopprocesscommalist
- {\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}%
- \processcommalist[#1]\currentcommalistcommand}
+ {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}%
+ \processcommalist[#1]\syst_helpers_comma_list_step}
\unexpanded\def\startprocesscommacommand[#1]#2\stopprocesscommacommand
- {\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}%
- \normalexpanded{\processcommalist[#1]}\currentcommalistcommand}
+ {\def\syst_helpers_comma_list_step##1{\def\currentcommalistitem{##1}#2}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_comma_list_step}
+
+\let\stopprocesscommalist \relax
+\let\stopprocesscommacommand\relax
%D \macros
%D {processaction,
@@ -1097,8 +1103,8 @@
% 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
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_two\s!default
\let\commalistelement\empty
#2%
\fi}
@@ -1106,19 +1112,19 @@
% met \quitcommalist tot meer dan 25\% sneller
\unexpanded\def\syst_helpers_do_compare_process_action_b[#1=>#2][#3]%
- {\edef\!!stringb{#1}%
- \ifx\!!stringa\!!stringb
+ {\edef\m_syst_string_two{#1}%
+ \ifx\m_syst_string_one\m_syst_string_two
\def\commalistelement{#3}%
#2%
\expandafter\quitcommalist
- \else\ifx\!!stringb\s!unknown
+ \else\ifx\m_syst_string_two\s!unknown
\def\commalistelement{#3}% beware of loops
#2%
\fi\fi}
\unexpanded\def\processaction[#1]#2[%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_a
\else
\let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_b
@@ -1127,23 +1133,23 @@
\processnextcommalist\relax\relax\syst_helpers_do_process_action[}
\unexpanded\def\syst_helpers_do_compare_process_action_c[#1=>#2][#3]%
- {\edef\!!stringa{#1}%
- \edef\!!stringb{#3}%
- \ifx\!!stringa\!!stringb
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#3}%
+ \ifx\m_syst_string_one\m_syst_string_two
\def\commalistelement{#3}%
#2%
\expandafter\quitprevcommalist
\else
- \edef\!!stringa{#1}%
- \ifx\!!stringa\s!unknown
+ \edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\s!unknown
\def\commalistelement{#3}%
#2%
\fi
\fi}
\unexpanded\def\processfirstactioninset[#1]%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\processaction
\else
\expandafter\syst_helpers_process_first_action_in_set_indeed
@@ -1157,26 +1163,28 @@
\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
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#3}%
+ \ifx\m_syst_string_one\m_syst_string_two
\def\commalistelement{#3}%
#2%
\expandafter\quitcommalist
\else
- \edef\!!stringa{#1}%
- \ifx\!!stringa\s!unknown
+ \edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\s!unknown
\def\commalistelement{#3}%
#2%
\fi
\fi}
+\installsystemnamespace{nextactionlevel}
+
\unexpanded\def\syst_helpers_do_process_all_actions_in_set
- {\csname\s!do\the\processlevel\endcsname}
+ {\csname\??nextactionlevel\the\processlevel\endcsname}
\unexpanded\def\processallactionsinset[#1]%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\processaction
\else
\expandafter\syst_helpers_process_all_actions_in_set_indeed
@@ -1185,7 +1193,7 @@
\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%
+ \expandafter\def\csname\??nextactionlevel\the\processlevel\endcsname##1%
{\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
@@ -1197,7 +1205,7 @@
{#1%
\let\nexttoken#4%
\global\advance\commalevel \plusone
- \expandafter\def\csname\s!next\the\commalevel\endcsname##1,%
+ \expandafter\def\csname\??nextcommalevel\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
@@ -1231,46 +1239,48 @@
%D \doifinsetelse {substring} {string} {then ...} {else ...}
%D \stoptyping
+\let\m_syst_sub_string\empty
+
\unexpanded\def\doifinstringelse#1%
- {\edef\@@@instring{#1}% expand #1 here
- \ifx\@@@instring\empty
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
\expandafter\thirdofthreearguments
\else
\expandafter\syst_helpers_do_if_in_string_else_indeed
\fi}
\unexpanded\def\syst_helpers_do_if_in_string_else_indeed#1%
- {\syst_helpers_do_if_in_string_else\@@@instring{#1}%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
\unexpanded\def\doifinstring#1%%
- {\edef\@@@instring{#1}% expand #1 here
- \ifx\@@@instring\empty
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
\expandafter\gobbletwoarguments
\else
\expandafter\syst_helpers_do_if_in_string_indeed
\fi}
\unexpanded\def\syst_helpers_do_if_in_string_indeed#1%
- {\syst_helpers_do_if_in_string_else\@@@instring{#1}%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
\unexpanded\def\doifnotinstring#1%%
- {\edef\@@@instring{#1}% expand #1 here
- \ifx\@@@instring\empty
+ {\edef\m_syst_sub_string{#1}% expand #1 here
+ \ifx\m_syst_sub_string\empty
\expandafter\gobbletwoarguments
\else
\expandafter\syst_helpers_do_if_not_in_string_indeed
\fi}
\unexpanded\def\syst_helpers_do_if_not_in_string_indeed#1%
- {\syst_helpers_do_if_in_string_else\@@@instring{#1}%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{#1}%
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
@@ -1280,8 +1290,8 @@
\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
+ \expandafter##\expandafter1#1##2##3\_e_o_s_{\unless\if##2@}% expand #1 here
+ \expandafter\syst_helpers_do_do_if_in_string_else\normalexpanded{#2#1}@@\_e_o_s_} % expand #2 here
%D The next alternative proved to be upto twice as fast on
%D tasks like checking reserved words in pretty verbatim
@@ -1297,33 +1307,31 @@
%D expansion.
\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
+ {\def\syst_helpers_do_do_if_in_csname_else##1#1##2##3\_e_o_s_
{\unless\if##2@}%
- \expandafter\syst_helpers_do_do_if_in_csname_else#2#1@@\war}
+ \expandafter\syst_helpers_do_do_if_in_csname_else#2#1@@\_e_o_s_}
\unexpanded\def\doifincsnameelse#1#2%
- {\edef\@@@instring{#1}%
- \expandafter\syst_helpers_do_if_in_csname_else\expandafter{\@@@instring}{#2}%
+ {\normalexpanded{\syst_helpers_do_if_in_csname_else{#1}}{#2}%
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
%D \macros
-%D {doifnumberelse}
+%D {doifnumberelse,doifnumber,doifnotnumber}
%D
-%D The next macro executes a command depending of the outcome
-%D of a test on numerals. This is probably one of the fastest
-%D test possible, exept from a less robust 10||step
-%D \type{\if}||ladder or some tricky \type{\lcode} checking.
+%D The next macro executes a command depending of the outcome of a test on
+%D numerals. This is probably one of the fastest test possible, exept from
+%D a less robust 10||step \type {\if}||ladder or some tricky \type {\lcode}
+%D checking.
%D
%D \starttyping
%D \doifnumberelse {string} {then ...} {else ...}
%D \stoptyping
%D
-%D The macro accepts \type{123}, \type{abc}, \type{{}},
-%D \type{\getal} and \type{\the\count...}. This macro is a
-%D rather dirty one.
+%D The macro accepts \type {123}, \type {abc}, \type {{}}, \type {\getal} and
+%D \type {\the\count...}. This macro is a rather dirty one.
\def\doifnumberelse#1% does not accept counters (fully expandable)
{\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
@@ -1332,6 +1340,35 @@
\expandafter\firstoftwoarguments
\fi}
+\def\doifnumber#1%
+ {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\doifnotnumber#1%
+ {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+%D \macros
+%D {setpercentdimen}
+%D
+%D \starttyping
+%D \scratchdimen=100pt \setpercentdimen\scratchdimen{10\letterpercent}
+%D \scratchdimen=100pt \setpercentdimen\scratchdimen{5pt}
+%D \scratchdimen \percentdimen \hsize {10\letterpercent}
+%D \stoptyping
+
+\def\percentdimen#1#2% dimen percentage (with %)
+ {\dimexpr\ctxcommand{percentageof("#2",\number#1)}\relax}
+
+\unexpanded\def\setpercentdimen#1#2% dimen percentage (with %)
+ {#1=\ctxcommand{percentageof("#2",\number#1)}\relax}
+
%D \macros
%D {makerawcommalist,
%D rawdoinsetelse,
@@ -1372,13 +1409,13 @@
\def\syst_helpers_raw_process_comma_item#1,#2% #2 eats up preceding space
{\if]#1\else
- \csname\s!next\the\commalevel\endcsname{#1}%
+ \csname\??nextcommalevel\the\commalevel\endcsname{#1}%
\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\let\csname\??nextcommalevel\the\commalevel\endcsname#2%
\expandafter\syst_helpers_raw_process_comma_item#1,],% \relax
\global\advance\commalevel \minusone }
@@ -1388,33 +1425,33 @@
% \def\rawdoifinsetelse#1#2{\doifinstringelse{,#1,}{,#2,}}
% \def\rawdoifinset #1#2{\doifinstring {,#1,}{,#2,}}
-\def\@@rawempty{,,}
+\def\m_syst_two_commas{,,}
\unexpanded\def\rawdoifinsetelse#1%
- {\edef\@@@instring{,#1,}% expand #1 here
- \ifx\@@@instring\@@rawempty
+ {\edef\m_syst_sub_string{,#1,}% expand #1 here
+ \ifx\m_syst_sub_string\m_syst_two_commas
\expandafter\thirdofthreearguments
\else
\expandafter\syst_helpers_raw_do_if_in_set_else
\fi}
\unexpanded\def\syst_helpers_raw_do_if_in_set_else#1%
- {\syst_helpers_do_if_in_string_else\@@@instring{,#1,}%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{,#1,}%
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
\unexpanded\def\rawdoifinset#1%
- {\edef\@@@instring{,#1,}% expand #1 here
- \ifx\@@@instring\@@rawempty
+ {\edef\m_syst_sub_string{,#1,}% expand #1 here
+ \ifx\m_syst_sub_string\m_syst_two_commas
\expandafter\gobbletwoarguments
\else
\expandafter\syst_helpers_raw_do_if_in_set
\fi}
\unexpanded\def\syst_helpers_raw_do_if_in_set#1%%
- {\syst_helpers_do_if_in_string_else\@@@instring{,#1,}%
+ {\syst_helpers_do_if_in_string_else\m_syst_sub_string{,#1,}%
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
@@ -1423,42 +1460,40 @@
%D Some more raw material:
\def\syst_helpers_do_raw_process_action[#1][#2]%
- {\def\syst_helpers_do_do_raw_process_action##1,#1=>##2,##3\war
+ {\def\syst_helpers_do_do_raw_process_action##1,#1=>##2,##3\_e_o_s_
{\if##3@\else
- \def\!!processaction{##2}%
+ \def\m_syst_helpers_process_action{##2}%
\fi}%
- \syst_helpers_do_do_raw_process_action,#2,#1=>,@\war}
+ \syst_helpers_do_do_raw_process_action,#2,#1=>,@\_e_o_s_}
\unexpanded\def\rawprocessaction[#1]#2[#3]%
- {\edef\!!stringa{#1}%
- \edef\!!stringb{undefined}% better \!!undefined
- \let\!!processaction\!!stringb
- \ifx\!!stringa\empty
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{undefined}% better \!!undefined
+ \let\m_syst_helpers_process_action\m_syst_string_two
+ \ifx\m_syst_string_one\empty
\expandafter\syst_helpers_do_raw_process_action\expandafter[\s!default][#3]%
\else
- \expandafter\syst_helpers_do_raw_process_action\expandafter[\!!stringa][#3]%
- \ifx\!!processaction\!!stringb
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\m_syst_string_one][#3]%
+ \ifx\m_syst_helpers_process_action\m_syst_string_two
\expandafter\syst_helpers_do_raw_process_action\expandafter[\s!unknown][#3]%
\fi
\fi
- \ifx\!!processaction\!!stringb
+ \ifx\m_syst_helpers_process_action\m_syst_string_two
\else
- \!!processaction
+ \m_syst_helpers_process_action
\fi}
-%D When we process the list \type{a,b,c,d,e}, the raw routine
-%D takes over 30\% less time, when we feed $20+$ character
-%D strings we gain about 20\%. Alternatives which use
-%D \type{\futurelet} perform worse. Part of the speedup is
-%D due to the \type{\let} and \type{\expandafter} in the test.
+%D When we process the list \type{a,b,c,d,e}, the raw routine takes over 30\% less
+%D time, when we feed $20+$ character strings we gain about 20\%. Alternatives which
+%D use \type{\futurelet} perform worse. Part of the speedup is due to the
+%D \type{\let} and \type{\expandafter} in the test.
%D \macros
%D {dosetvalue,dosetevalue,dosetgvalue,docopyvalue,doresetvalue,
%D dogetvalue}
%D
-%D When we are going to do assignments, we have to take
-%D multi||linguality into account. For the moment we keep
-%D things simple and single||lingual.
+%D When we are going to do assignments, we have to take multi||linguality into account.
+%D For the moment we keep things simple and single||lingual.
%D
%D \starttyping
%D \dosetvalue {label} {variable} {value}
@@ -1468,8 +1503,8 @@
%D \doresetvalue {label} {variable}
%D \stoptyping
%D
-%D These macros are in fact auxiliary ones and are not meant
-%D for use outside the assignment macros.
+%D These macros are in fact auxiliary ones and are not meant for use outside the
+%D assignment macros.
\def\dosetvalue#1#2% #3
{\expandafter\def\csname#1#2\endcsname} % {#3}}
@@ -1492,13 +1527,11 @@
%D \macros
%D {doassign,undoassign,doassignempty}
%D
-%D Assignments are the backbone of \CONTEXT. Abhorred by the
-%D concept of style file hacking, we took a considerable effort
-%D in building a parameterized system. Unfortunately there is a
-%D price to pay in terms of speed. Compared to other packages
-%D and taking the functionality of \CONTEXT\ into account, the
-%D total size of the format file is still very acceptable. Now
-%D how are these assignments done.
+%D Assignments are the backbone of \CONTEXT. Abhorred by the concept of style file
+%D hacking, we took a considerable effort in building a parameterized system.
+%D Unfortunately there is a price to pay in terms of speed. Compared to other
+%D packages and taking the functionality of \CONTEXT\ into account, the total size
+%D of the format file is still very acceptable. Now how are these assignments done.
%D
%D Assignments can be realized with:
%D
@@ -1519,38 +1552,36 @@
%D \def\labelvariable{value}
%D \stoptyping
%D
-%D We do check for the presence of an \type{=} and loudly
-%D complain of it's missed. We will redefine this macro later
-%D on, when a more advanced message mechanism is implemented.
+%D We do check for the presence of an \type{=} and loudly complain of it's missed. We
+%D will redefine this macro later on, when a more advanced message mechanism is
+%D implemented.
\newif\iferrorisfatal
-\def\waitonfatalerror
+\unexpanded\def\waitonfatalerror
{\iferrorisfatal\wait\fi}
-\def\showassignerror#1#2%
+\unexpanded\def\showassignerror#1#2%
{\writestatus{setup}{missing or ungrouped '=' after '#1' in line #2}%
\waitonfatalerror}
-\def\doassignempty[#1][#2=#3]%
+\unexpanded\def\doassignempty[#1][#2=#3]%
{\ifcsname#1#2\endcsname\else\dosetvalue{#1}{#2}{#3}\fi}
%D \macros
%D {getparameters,geteparameters,getgparameters,
%D forgetparameters}
%D
-%D Using the assignment commands directly is not our
-%D ideal of user friendly interfacing, so we take some further
-%D steps.
+%D Using the assignment commands directly is not our ideal of user friendly interfacing,
+%D so we take some further steps.
%D
%D \starttyping
%D \getparameters [label] [...=...,...=...]
%D \forgetparameters [label] [...=...,...=...]
%D \stoptyping
%D
-%D Again, the label identifies the category a variable
-%D belongs to. The second argument can be a comma separated
-%D list of assignments.
+%D Again, the label identifies the category a variable belongs to. The second argument
+%D can be a comma separated list of assignments.
%D
%D \starttyping
%D \getparameters
@@ -1567,8 +1598,7 @@
%D \stoptyping
%D
%D
-%D In the pre||multi||lingual stadium \CONTEXT\ took the next
-%D approach. With
+%D In the pre||multi||lingual stadium \CONTEXT\ took the next approach. With
%D
%D \starttyping
%D \def\??demo {@@demo}
@@ -1592,20 +1622,16 @@
%D \def\@@demobeta{2}
%D \stoptyping
%D
-%D Because we want to be able to distinguish the \type{!!}
-%D pre||tagged user supplied variables from internal
-%D counterparts, we will introduce a slightly different tag in
-%D the multi||lingual modules. There we will use \type{c!} or
-%D \type{v!}, depending on the context.
-%D
-%D By calling \type{\p!doassign} directly, we save ourselves
-%D some argument passing and gain some speed. Whatever
-%D optimizations we do, this command will always be one of the
-%D bigger bottlenecks.
+%D Because we want to be able to distinguish the \type{!!} pre||tagged user supplied
+%D variables from internal counterparts, we will introduce a slightly different tag
+%D in the multi||lingual modules. There we will use \type{c!} or \type{v!},
+%D depending on the context.
%D
-%D The alternative \type{\geteparameters} --- it's funny to
-%D see that this alternative saw the light so lately --- can be
-%D used to do expanded assigments.
+%D By calling \type{doassign} directly, we save ourselves some argument passing
+%D and gain some speed. Whatever optimizations we do, this command will always be
+%D one of the bigger bottlenecks. The alternative \type{\geteparameters} --- it's
+%D funny to see that this alternative saw the light so lately --- can be used to do
+%D expanded assigments.
\let\currentvalue\empty
@@ -1617,46 +1643,46 @@
\let\getexpandedparameters\geteparameters
-\def\dogetparameters#1[#2]#3[#4%
+\unexpanded\def\dogetparameters#1[#2]#3[#4%
{\if\noexpand#4]%
\expandafter\gobbleoneargument
\else
\let\setsomevalue#1%
- \def\p!dogetparameter{\p!doassign#2}%
- \expandafter\xdogetparameters
+ \def\syst_helpers_get_parameters_assign{\syst_helpers_get_parameters_assign_indeed#2}%
+ \expandafter\syst_helpers_get_parameters
\fi#4}
-\def\xdogetparameters#1]%
- {\xprocesscommaitem#1,],\@relax@}
+\def\syst_helpers_get_parameters#1]%
+ {\xprocesscommaitem#1,],\_e_o_p_}
-\def\xprocesscommaitem#1,#2% #2 takes space before ,
+\def\syst_helpers_process_comma_item#1,#2% #2 takes space before ,
{\if,#1,% dirty trick for testing #1=empty
- \expandafter\xprocesscommaitem
+ \expandafter\syst_helpers_process_comma_item
\else\if]#1%
\doubleexpandafter\gobbleoneargument
\else
- \p!dogetparameter\@relax@#1==\empty\@relax@
- \doubleexpandafter\xprocesscommaitem
+ \syst_helpers_get_parameters_assign\_e_o_p_#1==\empty\_e_o_p_
+ \doubleexpandafter\syst_helpers_process_comma_item
\fi\fi#2}
-\def\xshowassignerror#1#2#3%
+\def\syst_helpers_assign_error#1#2#3%
{\showassignerror{#2}{\the\inputlineno\space(#1)}}
-\def\p!n!doassign#1\@relax@#2=#3=#4#5\@relax@
+\def\syst_helpers_get_parameters_assign_normal#1\_e_o_p_#2=#3=#4#5\_e_o_p_
{\ifx\empty#2\empty
- \expandafter\xshowassignerror
+ \expandafter\syst_helpers_assign_error
\else\ifx#4\empty
- \doubleexpandafter\xshowassignerror
+ \doubleexpandafter\syst_helpers_assign_error
\else
\doubleexpandafter\setsomevalue
\fi\fi
{#1}{#2}{#3}}
-\def\p!e!doassign#1\@relax@#2=#3=#4#5\@relax@
+\def\syst_helpers_get_parameters_assign_error#1\_e_o_p_#2=#3=#4#5\_e_o_p_
{\ifx\empty#2\empty
- \expandafter\xshowassignerror
+ \expandafter\syst_helpers_assign_error
\else\ifx#4\empty
- \doubleexpandafter\xshowassignerror
+ \doubleexpandafter\syst_helpers_assign_error
\else
\ifcsname#1#2\endcsname
\expandafter\let\expandafter\currentvalue\csname#1#2\endcsname
@@ -1667,11 +1693,11 @@
\fi\fi
{#1}{#2}{#3}}
-\let\p!doassign\p!n!doassign
+\let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_normal
-\def\doassign [#1][#2]{\let\setsomevalue\dosetvalue \p!doassign#1\@relax@#2==\empty\@relax@}
-\def\doeassign [#1][#2]{\let\setsomevalue\dosetevalue \p!doassign#1\@relax@#2==\empty\@relax@}
-\def\undoassign[#1][#2]{\let\setsomevalue\doresetvalue\p!doassign#1\@relax@#2==\empty\@relax@}
+\unexpanded\def\doassign [#1][#2]{\let\setsomevalue\dosetvalue \syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_}
+\unexpanded\def\doeassign [#1][#2]{\let\setsomevalue\dosetevalue \syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_}
+\unexpanded\def\undoassign[#1][#2]{\let\setsomevalue\doresetvalue\syst_helpers_get_parameters_assign_indeed#1\_e_o_p_#2==\empty\_e_o_p_}
%D \macros
%D {processassignmentlist,processassignmentcommand,
@@ -1688,8 +1714,8 @@
%D worth the trouble and tokens.
\unexpanded\def\processassignmentlist[#1]#2% #2 == \command{key}{value]
- {\def\doprocessassignmententry##1{#2}% {##2}{##3} % namespace is ignored
- \dogetparameters\doprocessassignmententry[][#1]}
+ {\def\syst_helpers_process_assignment_entry##1{#2}% {##2}{##3} % namespace is ignored
+ \dogetparameters\syst_helpers_process_assignment_entry[][#1]}
\unexpanded\def\processassignmentcommand[#1]%
{\normalexpanded{\processassignmentlist[#1]}}
@@ -1704,9 +1730,8 @@
%D \macros{currentvalue}
%D
-%D Just in case a \type{\getparameter} argument itself ends up
-%D inside a \type{\write} or other expandable location, our
-%D new macro needs a default value.
+%D Just in case a \type{\getparameter} argument itself ends up inside a \type
+%D {\write} or other expandable location, our new macro needs a default value.
%D
%D \starttyping
%D \getparameters[xxx][aaa=bbb]\par
@@ -1716,7 +1741,8 @@
%D \getparameters[xxx][aaa]\par
%D \stoptyping
-%D \macros {expandparameters}
+%D \macros
+%D {expandparameters}
%D
%D Example usage:
%D
@@ -1733,26 +1759,27 @@
%D \startlines
%D \getbuffer
%D \stoplines
-
+%D
%D Here we hook in the code (beware, this is the optimized get **):
-\def\xdoget@n@parameters#1]%
- {\xprocesscommaitem#1,],\@relax@}
+\def\syst_helpers_get_parameters_normal#1]%
+ {\syst_helpers_process_comma_item#1,],\_e_o_p_}
-\def\xdoget@e@parameters#1]%
+\def\syst_helpers_get_parameters_expanded#1]%
{\let\dosetnvalue\setsomevalue
\let\setsomevalue\dosetevalue
- \let\p!doassign\p!e!doassign
+ \let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_error
\let\setsomevalue\dosetevalue
- \xprocesscommaitem#1,],\@relax@
- \let\p!doassign\p!n!doassign
+ \syst_helpers_process_comma_item#1,],\_e_o_p_
+ \let\syst_helpers_get_parameters_assign_indeed\syst_helpers_get_parameters_assign_normal
\let\setsomevalue\dosetnvalue
- \let\xdogetparameters\xdoget@n@parameters
+ \let\syst_helpers_get_parameters\syst_helpers_get_parameters_normal
\let\currentvalue\empty}
-\let\xdogetparameters\xdoget@n@parameters % **
+\let\syst_helpers_get_parameters\syst_helpers_get_parameters_normal % **
-\def\expandparameters{\let\xdogetparameters\xdoget@e@parameters}
+\unexpanded\def\expandparameters
+ {\let\syst_helpers_get_parameters\syst_helpers_get_parameters_expanded}
%D \macros
%D {getemptyparameters}
@@ -1764,9 +1791,9 @@
%D \getemptyparameters [label] [...=...,...=...]
%D \stoptyping
-\def\getemptyparameters[#1]#2[#3]%
- {\def\p!dogetemptyparameter##1{\doassignempty[#1][##1]}%
- \processcommalist[#3]\p!dogetemptyparameter}
+\unexpanded\def\getemptyparameters[#1]#2[#3]%
+ {\def\syst_helpers_get_empty_parameters##1{\doassignempty[#1][##1]}%
+ \processcommalist[#3]\syst_helpers_get_empty_parameters}
%D \macros
%D {copyparameters}
@@ -1801,8 +1828,8 @@
\unexpanded\def\copyparameters[#1]#2[#3]#4[#5]%
{\doifnot{#1}{#3}
- {\def\docopyparameter{\docopyvalue{#1}{#3}}% ##1
- \processcommalist[#5]\docopyparameter}}
+ {\def\syst_helpers_copy_parameter{\docopyvalue{#1}{#3}}% ##1
+ \processcommalist[#5]\syst_helpers_copy_parameter}}
%D \macros
%D {ifparameters,checkparameters}
@@ -1820,58 +1847,60 @@
\newif\ifparameters
-\def\p!checkparameters#1=#2#3\war%
+\def\syst_helpers_check_parameters#1=#2#3\_e_o_s_
{\if#2@\parametersfalse\else\parameterstrue\fi}
-\def\checkparameters[#1]%
- {\p!checkparameters#1=@@\war}
+\unexpanded\def\checkparameters[#1]%
+ {\syst_helpers_check_parameters#1=@@\_e_o_s_}
%D \macros
%D {getfromcommalist,getfromcommacommand,
%D commalistelement,
%D getcommalistsize,getcommacommandsize}
%D
-%D It's possible to get an element from a commalist or a
-%D command representing a commalist.
+%D It's possible to get an element from a commalist or a command representing
+%D a commalist.
%D
%D \starttyping
%D \getfromcommalist [string] [n]
%D \getfromcommacommand [string,\strings,string,...] [n]
%D \stoptyping
%D
-%D The difference betwee the two of them is the same as the
-%D difference between \type{\processcomma...}. The found string
-%D is stored in \type{\commalistelement}.
+%D The difference betwee the two of them is the same as the difference between
+%D \type {\processcomma...}. The found string is stored in \type
+%D {\commalistelement}.
%D
-%D We can calculate the size of a comma separated list by
-%D using:
+%D We can calculate the size of a comma separated list by using:
%D
%D \starttyping
%D \getcommalistsize [string,string,...]
%D \getcommacommandsize [string,\strings,string,...]
%D \stoptyping
%D
-%D Afterwards, the length is available in the macro
-%D \type{\commalistsize} (not a \COUNTER).
+%D Afterwards, the length is available in the macro \type {\commalistsize}
+%D (not a \COUNTER).
\newcount\commalistcounter
\def\commalistsize{0}
-\def\p!dogetcommalistsize#1%
+\def\syst_helpers_get_comma_list_size#1%
{\advance\commalistcounter\plusone}
-\def\getcommalistsize#1]% don't loose [{#1}]
+\unexpanded\def\getcommalistsize#1]% don't loose [{#1}]
{\commalistcounter\zerocount
- \processcommalist#1]\p!dogetcommalistsize % was [{#1}]
+ \processcommalist#1]\syst_helpers_get_comma_list_size % was [{#1}]
\edef\commalistsize{\the\commalistcounter}}
-\def\getcommacommandsize[#1]%
- {\edef\commacommand{#1}%
- \scratchtoks\expandafter{\expandafter[\commacommand]}%
- \expandafter\getcommalistsize\the\scratchtoks }
+% \def\getcommacommandsize[#1]%
+% {\edef\commacommand{#1}%
+% \scratchtoks\expandafter{\expandafter[\commacommand]}%
+% \expandafter\getcommalistsize\the\scratchtoks }
-\def\p!dogetfromcommalist#1%
+\unexpanded\def\getcommacommandsize[#1]%
+ {\normalexpanded{\getcommalistsize[#1]}}
+
+\def\syst_helpers_get_from_comma_list#1%
{\advance\commalistcounter \minusone
\ifcase\commalistcounter
\def\commalistelement{#1}%
@@ -1881,7 +1910,7 @@
\unexpanded\def\getfromcommalist[#1]#2[#3]%
{\let\commalistelement\empty
\commalistcounter#3\relax
- \processcommalist[#1]\p!dogetfromcommalist}
+ \processcommalist[#1]\syst_helpers_get_from_comma_list}
\unexpanded\def\getfromcommacommand[#1]%
{\normalexpanded{\getfromcommalist[#1]}}
@@ -1919,16 +1948,11 @@
%D \dogetcommalistelement1\from a,b,c\to\commalistelement
%D \stoptyping
-\def\dodogetcommalistelement#1\from#2,#3,#4,#5,#6,#7,#8\to#9%
+\def\syst_helpers_get_comma_list_element#1\from#2,#3,#4,#5,#6,#7,#8\to#9%
{\edef#9{\ifcase#1\relax\or#2\or#3\or#4\or#5\or#6\or#7\or#8\fi}}
-\def\dogetcommalistelement#1\from#2\to%
- {\dodogetcommalistelement#1\from#2,,,,,,\to}
-
-% check sources
-
\def\dogetcommacommandelement#1\from#2\to%
- {\expandafter\dodogetcommalistelement\expandafter#1\expandafter\from#2,,,,,,\to}
+ {\expandafter\syst_helpers_get_comma_list_element\expandafter#1\expandafter\from#2,,,,,,\to}
%D \macros
%D {dosingleargument,dodoubleargument,dotripleargument,
@@ -1984,13 +2008,15 @@
%D us to do some checking, we reimplemented the non||empty
%D ones.
-\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}
+% no longer a mesage:
+%
+% \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,
@@ -2013,8 +2039,7 @@
%D doquadrupleempty,doquintupleempty,dosixtupeempty,
%D doseventupleempty}
%D
-%D The empty argument supplying macros mentioned before, look
-%D like:
+%D The empty argument supplying macros mentioned before, look like:
%D
%D \starttyping
%D \dosingleempty \command
@@ -2022,11 +2047,11 @@
%D \dotripleempty \command
%D \doquadrupleempty \command
%D \doquintupleempty \command
-%D \dosixtupleempty \command
+%D \dosixtuple_empty \command
%D \doseventupleempty\command
%D \stoptyping
%D
-%D So \type{\dodoubleempty} leades to:
+%D So \type{\dodoubleempty} leads to:
%D
%D \starttyping
%D \command[#1][#2]
@@ -2041,16 +2066,16 @@
\setnewconstant\noexpectedarguments\zerocount
\setnewconstant\expectedarguments \zerocount
-\def\showargumenterror#1#2%
+\unexpanded\def\showargumenterror#1#2%
{\writestatus{system}{\number#1 argument(s) expected in line #2}}
-\def\doshowargumenterror
+\unexpanded\def\syst_helpers_argument_error
{\ifnum\expectedarguments>\noexpectedarguments
\showargumenterror{\number\expectedarguments}{\number\inputlineno}%
\fi
- \noshowargumenterror}
+ \syst_helpers_argument_reset}
-\def\noshowargumenterror
+\unexpanded\def\syst_helpers_argument_reset
{\let\expectedarguments\noexpectedarguments}
% \def\test[#1]{(#1)}
@@ -2074,193 +2099,193 @@
%D Single:
\unexpanded\def\dosingleempty#1%
- {\noshowargumenterror
+ {\syst_helpers_argument_reset
\doifnextoptionalelse
{\firstargumenttrue#1}%
- {\dosingleemptyNOPone#1}}
+ {\syst_helpers_single_empty_one_nop#1}}
-\def\dosingleemptyNOPone#1%
+\def\syst_helpers_single_empty_one_nop#1%
{\firstargumentfalse
#1[]}
%D Double
\unexpanded\def\dodoubleempty#1%
- {\noshowargumenterror
+ {\syst_helpers_argument_reset
\doifnextoptionalelse
- {\dodoubleemptyYESone#1}%
- {\dodoubleemptyNOPone#1}}
+ {\syst_helpers_double_empty_one_yes#1}%
+ {\syst_helpers_double_empty_one_nop#1}}
-\def\dodoubleemptyYESone#1[#2]%
+\def\syst_helpers_double_empty_one_yes#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
{\secondargumenttrue#1[{#2}]}%
- {\dodoubleemptyNOPtwo#1{#2}}}
+ {\syst_helpers_double_empty_two_nop#1{#2}}}
-\def\dodoubleemptyNOPone#1%
+\def\syst_helpers_double_empty_one_nop#1%
{\firstargumentfalse
\secondargumentfalse
#1[][]}
-\def\dodoubleemptyNOPtwo
+\def\syst_helpers_double_empty_two_nop
{\secondargumentfalse
\if_next_blank_space_token
- \expandafter\dodoubleemptyonespaced
+ \expandafter\syst_helpers_double_empty_one_spaced
\else
- \expandafter\dodoubleemptyonenormal
+ \expandafter\syst_helpers_double_empty_one_normal
\fi}
-\def\dodoubleemptyonespaced#1#2{#1[{#2}][] }
-\def\dodoubleemptyonenormal#1#2{#1[{#2}][]}
+\def\syst_helpers_double_empty_one_spaced#1#2{#1[{#2}][] }
+\def\syst_helpers_double_empty_one_normal#1#2{#1[{#2}][]}
% Three
\unexpanded\def\dotripleempty#1%
- {\noshowargumenterror
+ {\syst_helpers_argument_reset
\doifnextoptionalelse
- {\dotripleemptyYESone#1}%
- {\dotripleemptyNOPone#1}}
+ {\syst_helpers_triple_empty_one_yes#1}%
+ {\syst_helpers_triple_empty_one_nop#1}}
-\def\dotripleemptyYESone#1[#2]%
+\def\syst_helpers_triple_empty_one_yes#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
- {\dotripleemptyYEStwo#1{#2}}%
- {\dotripleemptyNOPtwo#1{#2}}}
+ {\syst_helpers_triple_empty_two_yes#1{#2}}%
+ {\syst_helpers_triple_empty_two_nop#1{#2}}}
-\def\dotripleemptyYEStwo#1#2[#3]%
+\def\syst_helpers_triple_empty_two_yes#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
{\thirdargumenttrue#1[{#2}][{#3}]}%
- {\dotripleemptyNOPthree#1{#2}{#3}}}
+ {\syst_helpers_triple_empty_three_nop#1{#2}{#3}}}
-\def\dotripleemptyNOPone#1%
+\def\syst_helpers_triple_empty_one_nop#1%
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
#1[][][]}
-\def\dotripleemptyNOPtwo
+\def\syst_helpers_triple_empty_two_nop
{\secondargumentfalse
\thirdargumentfalse
\if_next_blank_space_token
- \expandafter\dotripleemptytwospaced
+ \expandafter\syst_helpers_triple_empty_two_spaced
\else
- \expandafter\dotripleemptytwonormal
+ \expandafter\syst_helpers_triple_empty_two_normal
\fi}
-\def\dotripleemptyNOPthree
+\def\syst_helpers_triple_empty_three_nop
{\thirdargumentfalse
\if_next_blank_space_token
- \expandafter\dotripleemptythreespaced
+ \expandafter\syst_helpers_triple_empty_three_spaced
\else
- \expandafter\dotripleemptythreenormal
+ \expandafter\syst_helpers_triple_empty_three_normal
\fi}
-\def\dotripleemptytwospaced #1#2{#1[{#2}][][] }
-\def\dotripleemptytwonormal #1#2{#1[{#2}][][]}
-\def\dotripleemptythreespaced#1#2#3{#1[{#2}][{#3}][] }
-\def\dotripleemptythreenormal#1#2#3{#1[{#2}][{#3}][]}
+\def\syst_helpers_triple_empty_two_spaced #1#2{#1[{#2}][][] }
+\def\syst_helpers_triple_empty_two_normal #1#2{#1[{#2}][][]}
+\def\syst_helpers_triple_empty_three_spaced#1#2#3{#1[{#2}][{#3}][] }
+\def\syst_helpers_triple_empty_three_normal#1#2#3{#1[{#2}][{#3}][]}
%D Four:
\unexpanded\def\doquadrupleempty#1%
- {\noshowargumenterror
+ {\syst_helpers_argument_reset
\doifnextoptionalelse
- {\doquadrupleemptyYESone#1}%
- {\doquadrupleemptyNOPone#1}}
+ {\syst_helpers_quadruple_empty_one_yes#1}%
+ {\syst_helpers_quadruple_empty_one_nop#1}}
-\def\doquadrupleemptyYESone#1[#2]%
+\def\syst_helpers_quadruple_empty_one_yes#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
- {\doquadrupleemptyYEStwo#1{#2}}%
- {\doquadrupleemptyNOPtwo#1{#2}}}
+ {\syst_helpers_quadruple_empty_two_yes#1{#2}}%
+ {\syst_helpers_quadruple_empty_two_nop#1{#2}}}
-\def\doquadrupleemptyYEStwo#1#2[#3]%
+\def\syst_helpers_quadruple_empty_two_yes#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
- {\doquadrupleemptyYESthree#1{#2}{#3}}%
- {\doquadrupleemptyNOPthree#1{#2}{#3}}}
+ {\syst_helpers_quadruple_empty_three_yes#1{#2}{#3}}%
+ {\syst_helpers_quadruple_empty_three_nop#1{#2}{#3}}}
-\def\doquadrupleemptyYESthree#1#2#3[#4]%
+\def\syst_helpers_quadruple_empty_three_yes#1#2#3[#4]%
{\thirdargumenttrue
\doifnextoptionalelse
{\fourthargumenttrue#1[{#2}][{#3}][{#4}]}%
- {\doquadrupleemptyNOPfour#1{#2}{#3}{#4}}}
+ {\syst_helpers_quadruple_empty_four_nop#1{#2}{#3}{#4}}}
-\def\doquadrupleemptyNOPone#1%
+\def\syst_helpers_quadruple_empty_one_nop#1%
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
#1[][][][]}
-\def\doquadrupleemptyNOPtwo
+\def\syst_helpers_quadruple_empty_two_nop
{\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
\if_next_blank_space_token
- \expandafter\doquadrupleemptytwospaced
+ \expandafter\syst_helpers_quadruple_empty_two_spaced
\else
- \expandafter\doquadrupleemptytwonormal
+ \expandafter\syst_helpers_quadruple_empty_two_normal
\fi}
-\def\doquadrupleemptyNOPthree
+\def\syst_helpers_quadruple_empty_three_nop
{\thirdargumentfalse
\fourthargumentfalse
\if_next_blank_space_token
- \expandafter\doquadrupleemptythreespaced
+ \expandafter\syst_helpers_quadruple_empty_three_spaced
\else
- \expandafter\doquadrupleemptythreenormal
+ \expandafter\syst_helpers_quadruple_empty_three_normal
\fi}
-\def\doquadrupleemptyNOPfour
+\def\syst_helpers_quadruple_empty_four_nop
{\fourthargumentfalse
\if_next_blank_space_token
- \expandafter\doquadrupleemptyfourspaced
+ \expandafter\syst_helpers_quadruple_empty_four_spaced
\else
- \expandafter\doquadrupleemptyfournormal
+ \expandafter\syst_helpers_quadruple_empty_four_normal
\fi}
-\def\doquadrupleemptytwospaced #1#2{#1[{#2}][][][] }
-\def\doquadrupleemptytwonormal #1#2{#1[{#2}][][][]}
-\def\doquadrupleemptythreespaced #1#2#3{#1[{#2}][{#3}][][] }
-\def\doquadrupleemptythreenormal #1#2#3{#1[{#2}][{#3}][][]}
-\def\doquadrupleemptyfourspaced #1#2#3#4{#1[{#2}][{#3}][{#4}][] }
-\def\doquadrupleemptyfournormal #1#2#3#4{#1[{#2}][{#3}][{#4}][]}
+\def\syst_helpers_quadruple_empty_two_spaced #1#2{#1[{#2}][][][] }
+\def\syst_helpers_quadruple_empty_two_normal #1#2{#1[{#2}][][][]}
+\def\syst_helpers_quadruple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][] }
+\def\syst_helpers_quadruple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][]}
+\def\syst_helpers_quadruple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][] }
+\def\syst_helpers_quadruple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][]}
%D Five:
\unexpanded\def\doquintupleempty#1%
- {\noshowargumenterror
+ {\syst_helpers_argument_reset
\doifnextoptionalelse
- {\doquintupleemptyYESone#1}%
- {\doquintupleemptyNOPone#1}}
+ {\syst_helpers_quintuple_empty_one_yes#1}%
+ {\syst_helpers_quintuple_empty_one_nop#1}}
-\def\doquintupleemptyYESone#1[#2]%
+\def\syst_helpers_quintuple_empty_one_yes#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
- {\doquintupleemptyYEStwo#1{#2}}%
- {\doquintupleemptyNOPtwo#1{#2}}}
+ {\syst_helpers_quintuple_empty_two_yes#1{#2}}%
+ {\syst_helpers_quintuple_empty_two_nop#1{#2}}}
-\def\doquintupleemptyYEStwo#1#2[#3]%
+\def\syst_helpers_quintuple_empty_two_yes#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
- {\doquintupleemptyYESthree#1{#2}{#3}}%
- {\doquintupleemptyNOPthree#1{#2}{#3}}}
+ {\syst_helpers_quintuple_empty_three_yes#1{#2}{#3}}%
+ {\syst_helpers_quintuple_empty_three_nop#1{#2}{#3}}}
-\def\doquintupleemptyYESthree#1#2#3[#4]%
+\def\syst_helpers_quintuple_empty_three_yes#1#2#3[#4]%
{\thirdargumenttrue
\doifnextoptionalelse
- {\doquintupleemptyYESfour#1{#2}{#3}{#4}}%
- {\doquintupleemptyNOPfour#1{#2}{#3}{#4}}}
+ {\syst_helpers_quintuple_empty_four_yes#1{#2}{#3}{#4}}%
+ {\syst_helpers_quintuple_empty_four_nop#1{#2}{#3}{#4}}}
-\def\doquintupleemptyYESfour#1#2#3#4[#5]%
+\def\syst_helpers_quintuple_empty_four_yes#1#2#3#4[#5]%
{\fourthargumenttrue
\doifnextoptionalelse
{\fifthargumenttrue#1[{#2}][{#3}][{#4}][{#5}]}%
- {\doquintupleemptyNOPfive#1{#2}{#3}{#4}{#5}}}
+ {\syst_helpers_quintuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
-\def\doquintupleemptyNOPone#1%
+\def\syst_helpers_quintuple_empty_one_nop#1%
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
@@ -2268,92 +2293,92 @@
\fifthargumentfalse
#1[][][][][]}
-\def\doquintupleemptyNOPtwo
+\def\syst_helpers_quintuple_empty_two_nop
{\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
\if_next_blank_space_token
- \expandafter\doquintupleemptytwospaced
+ \expandafter\syst_helpers_quintuple_empty_two_spaced
\else
- \expandafter\doquintupleemptytwonormal
+ \expandafter\syst_helpers_quintuple_empty_two_normal
\fi}
-\def\doquintupleemptyNOPthree
+\def\syst_helpers_quintuple_empty_three_nop
{\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
\if_next_blank_space_token
- \expandafter\doquintupleemptythreespaced
+ \expandafter\syst_helpers_quintuple_empty_three_spaced
\else
- \expandafter\doquintupleemptythreenormal
+ \expandafter\syst_helpers_quintuple_empty_three_normal
\fi}
-\def\doquintupleemptyNOPfour
+\def\syst_helpers_quintuple_empty_four_nop
{\fourthargumentfalse
\fifthargumentfalse
\if_next_blank_space_token
- \expandafter\doquintupleemptyfourspaced
+ \expandafter\syst_helpers_quintuple_empty_four_spaced
\else
- \expandafter\doquintupleemptyfournormal
+ \expandafter\syst_helpers_quintuple_empty_four_normal
\fi}
-\def\doquintupleemptyNOPfive
+\def\syst_helpers_quintuple_empty_five_nop
{\fifthargumentfalse
\if_next_blank_space_token
- \expandafter\doquintupleemptyfivespaced
+ \expandafter\syst_helpers_quintuple_empty_five_spaced
\else
- \expandafter\doquintupleemptyfivenormal
+ \expandafter\syst_helpers_quintuple_empty_five_normal
\fi}
-\def\doquintupleemptytwospaced #1#2{#1[{#2}][][][][] }
-\def\doquintupleemptytwonormal #1#2{#1[{#2}][][][][]}
-\def\doquintupleemptythreespaced #1#2#3{#1[{#2}][{#3}][][][] }
-\def\doquintupleemptythreenormal #1#2#3{#1[{#2}][{#3}][][][]}
-\def\doquintupleemptyfourspaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][] }
-\def\doquintupleemptyfournormal #1#2#3#4{#1[{#2}][{#3}][{#4}][][]}
-\def\doquintupleemptyfivespaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][] }
-\def\doquintupleemptyfivenormal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][]}
+\def\syst_helpers_quintuple_empty_two_spaced #1#2{#1[{#2}][][][][] }
+\def\syst_helpers_quintuple_empty_two_normal #1#2{#1[{#2}][][][][]}
+\def\syst_helpers_quintuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][] }
+\def\syst_helpers_quintuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][]}
+\def\syst_helpers_quintuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][] }
+\def\syst_helpers_quintuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][]}
+\def\syst_helpers_quintuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][] }
+\def\syst_helpers_quintuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][]}
%D Six
\unexpanded\def\dosixtupleempty#1%
- {\noshowargumenterror
+ {\syst_helpers_argument_reset
\doifnextoptionalelse
- {\dosixtupleemptyYESone#1}
- {\dosixtupleemptyNOPone#1}}
+ {\syst_helpers_sixtuple_empty_one_yes#1}
+ {\syst_helpers_sixtuple_empty_one_nop#1}}
-\def\dosixtupleemptyYESone#1[#2]%
+\def\syst_helpers_sixtuple_empty_one_yes#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
- {\dosixtupleemptyYEStwo#1{#2}}%
- {\dosixtupleemptyNOPtwo#1{#2}}}
+ {\syst_helpers_sixtuple_empty_two_yes#1{#2}}%
+ {\syst_helpers_sixtuple_empty_two_nop#1{#2}}}
-\def\dosixtupleemptyYEStwo#1#2[#3]%
+\def\syst_helpers_sixtuple_empty_two_yes#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
- {\dosixtupleemptyYESthree#1{#2}{#3}}%
- {\dosixtupleemptyNOPthree#1{#2}{#3}}}
+ {\syst_helpers_sixtuple_empty_three_yes#1{#2}{#3}}%
+ {\syst_helpers_sixtuple_empty_three_nop#1{#2}{#3}}}
-\def\dosixtupleemptyYESthree#1#2#3[#4]%
+\def\syst_helpers_sixtuple_empty_three_yes#1#2#3[#4]%
{\thirdargumenttrue
\doifnextoptionalelse
- {\dosixtupleemptyYESfour#1{#2}{#3}{#4}}%
- {\dosixtupleemptyNOPfour#1{#2}{#3}{#4}}}
+ {\syst_helpers_sixtuple_empty_four_yes#1{#2}{#3}{#4}}%
+ {\syst_helpers_sixtuple_empty_four_nop#1{#2}{#3}{#4}}}
-\def\dosixtupleemptyYESfour#1#2#3#4[#5]%
+\def\syst_helpers_sixtuple_empty_four_yes#1#2#3#4[#5]%
{\fourthargumenttrue
\doifnextoptionalelse
- {\dosixtupleemptyYESfive#1{#2}{#3}{#4}{#5}}%
- {\dosixtupleemptyNOPfive#1{#2}{#3}{#4}{#5}}}
+ {\syst_helpers_sixtuple_empty_five_yes#1{#2}{#3}{#4}{#5}}%
+ {\syst_helpers_sixtuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
-\def\dosixtupleemptyYESfive#1#2#3#4#5[#6]%
+\def\syst_helpers_sixtuple_empty_five_yes#1#2#3#4#5[#6]%
{\fifthargumenttrue
\doifnextoptionalelse
{\sixthargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}]}%
- {\dosixtupleemptyNOPsix#1{#2}{#3}{#4}{#5}{#6}}}
+ {\syst_helpers_sixtuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}}
-\def\dosixemptyNOPone#1%
+\def\syst_helpers_sixtuple_empty_one_nop#1%
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
@@ -2362,112 +2387,112 @@
\sixthargumentfalse
#1[][][][][][]}
-\def\dosixtupleemptyNOPtwo
+\def\syst_helpers_sixtuple_empty_two_nop
{\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\dosixemptytwospaced
+ \expandafter\syst_helpers_sixtuple_empty_two_spaced
\else
- \expandafter\dosixemptytwonormal
+ \expandafter\syst_helpers_sixtuple_empty_two_normal
\fi}
-\def\dosixtupleemptyNOPthree
+\def\syst_helpers_sixtuple_empty_three_nop
{\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\dosixemptythreespaced
+ \expandafter\syst_helpers_sixtuple_empty_three_spaced
\else
- \expandafter\dosixemptythreenormal
+ \expandafter\syst_helpers_sixtuple_empty_three_normal
\fi}
-\def\dosixtupleemptyNOPfour
+\def\syst_helpers_sixtuple_empty_four_nop
{\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\dosixemptyfourspaced
+ \expandafter\syst_helpers_sixtuple_empty_four_spaced
\else
- \expandafter\dosixemptyfournormal
+ \expandafter\syst_helpers_sixtuple_empty_four_normal
\fi}
-\def\dosixtupleemptyNOPfive
+\def\syst_helpers_sixtuple_empty_five_nop
{\fifthargumentfalse
\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\dosixemptyfivespaced
+ \expandafter\syst_helpers_sixtuple_empty_five_spaced
\else
- \expandafter\dosixemptyfivenormal
+ \expandafter\syst_helpers_sixtuple_empty_five_normal
\fi}
-\def\dosixtupleemptyNOPsix
+\def\syst_helpers_sixtuple_empty_six_nop
{\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\dosixemptysixspaced
+ \expandafter\syst_helpers_sixtuple_empty_six_spaced
\else
- \expandafter\dosixemptysixnormal
+ \expandafter\syst_helpers_sixtuple_empty_six_normal
\fi}
-\def\dosixemptytwospaced #1#2{#1[{#2}][][][][][] }
-\def\dosixemptytwonormal #1#2{#1[{#2}][][][][][]}
-\def\dosixemptythreespaced #1#2#3{#1[{#2}][{#3}][][][][] }
-\def\dosixemptythreenormal #1#2#3{#1[{#2}][{#3}][][][][]}
-\def\dosixemptyfourspaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][] }
-\def\dosixemptyfournormal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][]}
-\def\dosixemptyfivespaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][] }
-\def\dosixemptyfivenormal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][]}
-\def\dosixemptysixspaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][] }
-\def\dosixemptysixnormal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][]}
+\def\syst_helpers_sixtuple_empty_two_spaced #1#2{#1[{#2}][][][][][] }
+\def\syst_helpers_sixtuple_empty_two_normal #1#2{#1[{#2}][][][][][]}
+\def\syst_helpers_sixtuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][][] }
+\def\syst_helpers_sixtuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][][]}
+\def\syst_helpers_sixtuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][] }
+\def\syst_helpers_sixtuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][]}
+\def\syst_helpers_sixtuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][] }
+\def\syst_helpers_sixtuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][]}
+\def\syst_helpers_sixtuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][] }
+\def\syst_helpers_sixtuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][]}
%D Seven:
\unexpanded\def\doseventupleempty#1%
- {\noshowargumenterror
+ {\syst_helpers_argument_reset
\doifnextoptionalelse
- {\doseventupleemptyYESone#1}%
- {\doseventupleemptyNOPone#1}}
+ {\syst_helpers_seventuple_empty_one_yes#1}%
+ {\syst_helpers_seventuple_empty_one_nop#1}}
-\def\doseventupleemptyYESone#1[#2]%
+\def\syst_helpers_seventuple_empty_one_yes#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
- {\doseventupleemptyYEStwo#1{#2}}%
- {\doseventupleemptyNOPtwo#1{#2}}}
+ {\syst_helpers_seventuple_empty_two_yes#1{#2}}%
+ {\syst_helpers_seventuple_empty_two_nop#1{#2}}}
-\def\doseventupleemptyYEStwo#1#2[#3]%
+\def\syst_helpers_seventuple_empty_two_yes#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
- {\doseventupleemptyYESthree#1{#2}{#3}}%
- {\doseventupleemptyNOPthree#1{#2}{#3}}}
+ {\syst_helpers_seventuple_empty_three_yes#1{#2}{#3}}%
+ {\syst_helpers_seventuple_empty_three_nop#1{#2}{#3}}}
-\def\doseventupleemptyYESthree#1#2#3[#4]%
+\def\syst_helpers_seventuple_empty_three_yes#1#2#3[#4]%
{\thirdargumenttrue
\doifnextoptionalelse
- {\doseventupleemptyYESfour#1{#2}{#3}{#4}}%
- {\doseventupleemptyNOPfour#1{#2}{#3}{#4}}}
+ {\syst_helpers_seventuple_empty_four_yes#1{#2}{#3}{#4}}%
+ {\syst_helpers_seventuple_empty_four_nop#1{#2}{#3}{#4}}}
-\def\doseventupleemptyYESfour#1#2#3#4[#5]%
+\def\syst_helpers_seventuple_empty_four_yes#1#2#3#4[#5]%
{\fourthargumenttrue
\doifnextoptionalelse
- {\doseventupleemptyYESfive#1{#2}{#3}{#4}{#5}}%
- {\doseventupleemptyNOPfive#1{#2}{#3}{#4}{#5}}}
+ {\syst_helpers_seventuple_empty_five_yes#1{#2}{#3}{#4}{#5}}%
+ {\syst_helpers_seventuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
-\def\doseventupleemptyYESfive#1#2#3#4#5[#6]%
+\def\syst_helpers_seventuple_empty_five_yes#1#2#3#4#5[#6]%
{\fifthargumenttrue
\doifnextoptionalelse
- {\doseventupleemptyYESsix#1{#2}{#3}{#4}{#5}{#6}}%
- {\doseventupleemptyNOPsix#1{#2}{#3}{#4}{#5}{#6}}}
+ {\syst_helpers_seventuple_empty_six_yes#1{#2}{#3}{#4}{#5}{#6}}%
+ {\syst_helpers_seventuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}}
-\def\doseventupleemptyYESsix#1#2#3#4#5#6[#7]%
+\def\syst_helpers_seventuple_empty_six_yes#1#2#3#4#5#6[#7]%
{\sixthargumenttrue
\doifnextoptionalelse
{\seventhargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}]}%
- {\doseventupleemptyNOPseven#1{#2}{#3}{#4}{#5}{#6}{#7}}}
+ {\syst_helpers_seventuple_empty_seven_nop#1{#2}{#3}{#4}{#5}{#6}{#7}}}
-\def\dosevenemptyNOPone#1%
+\def\syst_helpers_seventuple_empty_one_nop#1%
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
@@ -2477,7 +2502,7 @@
\seventhargumentfalse
#1[][][][][][][]}
-\def\doseventupleemptyNOPtwo
+\def\syst_helpers_seventuple_empty_two_nop
{\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
@@ -2485,73 +2510,81 @@
\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\dosevenemptytwospaced
+ \expandafter\syst_helpers_seventuple_empty_two_spaced
\else
- \expandafter\dosevenemptytwonormal
+ \expandafter\syst_helpers_seventuple_empty_two_normal
\fi}
-\def\doseventupleemptyNOPthree
+\def\syst_helpers_seventuple_empty_three_nop
{\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\dosevenemptythreespaced
+ \expandafter\syst_helpers_seventuple_empty_three_spaced
\else
- \expandafter\dosevenemptythreenormal
+ \expandafter\syst_helpers_seventuple_empty_three_normal
\fi}
-\def\doseventupleemptyNOPfour
+\def\syst_helpers_seventuple_empty_four_nop
{\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\dosevenemptyfourspaced
+ \expandafter\syst_helpers_seventuple_empty_four_spaced
\else
- \expandafter\dosevenemptyfournormal
+ \expandafter\syst_helpers_seventuple_empty_four_normal
\fi}
-\def\doseventupleemptyNOPfive
+\def\syst_helpers_seventuple_empty_five_nop
{\fifthargumentfalse
\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\dosevenemptyfivespaced
+ \expandafter\syst_helpers_seventuple_empty_five_spaced
\else
- \expandafter\dosevenemptyfivenormal
+ \expandafter\syst_helpers_seventuple_empty_five_normal
\fi}
-\def\doseventupleemptyNOPsix
+\def\syst_helpers_seventuple_empty_six_nop
{\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\dosevenemptysixspaced
+ \expandafter\syst_helpers_seventuple_empty_six_spaced
\else
- \expandafter\dosevenemptysixnormal
+ \expandafter\syst_helpers_seventuple_empty_six_normal
\fi}
-\def\doseventupleemptyNOPseven
+\def\syst_helpers_seventuple_empty_seven_nop
{\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\dosevenemptysevenspaced
- \else
- \expandafter\dosevenemptysevennormal
- \fi}
-
-\def\dosevenemptytwospaced #1#2{#1[{#2}][][][][][][] }
-\def\dosevenemptytwonormal #1#2{#1[{#2}][][][][][][]}
-\def\dosevenemptythreespaced #1#2#3{#1[{#2}][{#3}][][][][][] }
-\def\dosevenemptythreenormal #1#2#3{#1[{#2}][{#3}][][][][][]}
-\def\dosevenemptyfourspaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][] }
-\def\dosevenemptyfournormal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][]}
-\def\dosevenemptyfivespaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][] }
-\def\dosevenemptyfivenormal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][]}
-\def\dosevenemptysixspaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][] }
-\def\dosevenemptysixnormal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][]}
-\def\dosevenemptysevenspaced#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][] }
-\def\dosevenemptysevennormal#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][]}
+ \expandafter\syst_helpers_seventuple_empty_seven_spaced
+ \else
+ \expandafter\syst_helpers_seventuple_empty_seven_normal
+ \fi}
+
+\def\syst_helpers_seventuple_empty_two_spaced #1#2{#1[{#2}][][][][][][] }
+\def\syst_helpers_seventuple_empty_two_normal #1#2{#1[{#2}][][][][][][]}
+\def\syst_helpers_seventuple_empty_three_spaced #1#2#3{#1[{#2}][{#3}][][][][][] }
+\def\syst_helpers_seventuple_empty_three_normal #1#2#3{#1[{#2}][{#3}][][][][][]}
+\def\syst_helpers_seventuple_empty_four_spaced #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][] }
+\def\syst_helpers_seventuple_empty_four_normal #1#2#3#4{#1[{#2}][{#3}][{#4}][][][][]}
+\def\syst_helpers_seventuple_empty_five_spaced #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][] }
+\def\syst_helpers_seventuple_empty_five_normal #1#2#3#4#5{#1[{#2}][{#3}][{#4}][{#5}][][][]}
+\def\syst_helpers_seventuple_empty_six_spaced #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][] }
+\def\syst_helpers_seventuple_empty_six_normal #1#2#3#4#5#6{#1[{#2}][{#3}][{#4}][{#5}][{#6}][][]}
+\def\syst_helpers_seventuple_empty_seven_spaced#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][] }
+\def\syst_helpers_seventuple_empty_seven_normal#1#2#3#4#5#6#7{#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}][]}
+
+\let\dosingleargument \dosingleempty
+\let\dodoubleargument \dodoubleempty
+\let\dotripleargument \dotripleempty
+\let\doquadrupleargument \doquadrupleempty
+\let\doquintupleargument \doquintupleempty
+\let\dosixtupleargument \dosixtupleempty
+\let\doseventupleargument\doseventupleempty
%D \macros
%D {strippedcsname}
@@ -2628,22 +2661,20 @@
%D worthwile to offer two more alternatives. Watch the build
%D in protection.
-\def\docomplexorsimple#1#2%
+\unexpanded\def\syst_helpers_complex_or_simple#1#2%
{\doifnextoptionalelse{\firstargumenttrue#1}{\firstargumentfalse#2}}
-\def\docomplexorsimpleempty#1%
+\unexpanded\def\syst_helpers_complex_or_simple_empty#1%
{\doifnextoptionalelse{\firstargumenttrue#1}{\firstargumentfalse#1[]}}
\unexpanded\def\definecomplexorsimple#1%
- {\unexpanded\edef#1%
- {\noexpand\docomplexorsimple
- \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname
- \expandafter\noexpand\csname\s!simple \strippedcsname#1\endcsname}}
+ {\unexpanded\edef#1{\syst_helpers_complex_or_simple
+ \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
- \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname}}
+ {\unexpanded\edef#1{\syst_helpers_complex_or_simple_empty
+ \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname}}
%D These commands are called as:
%D
@@ -2679,8 +2710,10 @@
%D We can add additional definitions later when we have defined
%D \type {\appendtoks}.
-\def \permitspacesbetweengroups{\let\@@permitspacesbetweengroups\zerocount}
-\def\dontpermitspacesbetweengroups{\let\@@permitspacesbetweengroups\plusone}
+\newconditional\c_syst_helpers_permit_spaces_between_groups
+
+\def \permitspacesbetweengroups{\settrue \c_syst_helpers_permit_spaces_between_groups}
+\def\dontpermitspacesbetweengroups{\setfalse\c_syst_helpers_permit_spaces_between_groups}
\dontpermitspacesbetweengroups
@@ -2689,94 +2722,94 @@
%D potentially being an \type {conditional} token. Okay, these macros
%D are not called that often but it saves crap when tracing.
-\def\dodogetgroupargument
+\unexpanded\def\syst_helpers_get_grouped_argument#1#2%
+ {\let\syst_helpers_get_grouped_argument_yes#1%
+ \let\syst_helpers_get_grouped_argument_nop#2%
+ \futurelet\nextargument\syst_helpers_get_grouped_argument_indeed}
+
+\def\syst_helpers_get_grouped_argument_indeed
{\ifx\nextargument\bgroup
- \expandafter\dodogetgroupargumentA
+ \expandafter\syst_helpers_get_grouped_argument_a
\else
- \expandafter\dodogetgroupargumentB
+ \expandafter\syst_helpers_get_grouped_argument_b
\fi}
-\def\dodogetgroupargumentA
- {\noshowargumenterror
- \dogroupargumentyes\dodogetargument}
+\def\syst_helpers_get_grouped_argument_a
+ {\syst_helpers_argument_reset
+ \syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nested}
-\def\dodogetgroupargumentB
- {\ifcase\@@permitspacesbetweengroups
- \expandafter\dodogetgroupargumentF
+\def\syst_helpers_get_grouped_argument_b
+ {\ifconditional\c_syst_helpers_permit_spaces_between_groups
+ \expandafter\syst_helpers_get_grouped_argument_f
\else
- \expandafter\dodogetgroupargumentD
+ \expandafter\syst_helpers_get_grouped_argument_d
\fi}
-\def\dodogetgroupargumentD
- {\doshowargumenterror
- \dogroupargumentnop\dodogetargument{}}
+\def\syst_helpers_get_grouped_argument_d
+ {\syst_helpers_argument_error
+ \syst_helpers_get_grouped_argument_nop\syst_helpers_get_grouped_argument_nested{}}
\begingroup
- \def\\ {\dogetgroupargument\dogroupargumentyes\dogroupargumentnop}
- \global\let\dodogetgroupargumentE\\
+ \def\\ {\syst_helpers_get_grouped_argument\syst_helpers_get_grouped_argument_yes\syst_helpers_get_grouped_argument_nop}
+ \global\let\syst_helpers_get_grouped_argument_e\\
\endgroup
-\def\dodogetgroupargumentF
+\def\syst_helpers_get_grouped_argument_f
{\ifx\nextargument\blankspace
- \expandafter\dodogetgroupargumentE % G
+ \expandafter\syst_helpers_get_grouped_argument_e % g
\else
- \expandafter\dodogetgroupargumentD % H
+ \expandafter\syst_helpers_get_grouped_argument_d % h
\fi}
-\def\dogetgroupargument#1#2%
- {\let\dogroupargumentyes#1%
- \let\dogroupargumentnop#2%
- \futurelet\nextargument\dodogetgroupargument}
-
\def\dosinglegroupempty#1%
- {\def\dodogetargument%
+ {\def\syst_helpers_get_grouped_argument_nested
{\dontpermitspacesbetweengroups
#1}%
- \dogetgroupargument\firstargumenttrue\firstargumentfalse}
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
\def\dodoublegroupempty#1%
- {\def\dodogetargument##1%
- {\def\dodogetargument%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested
{\dontpermitspacesbetweengroups
#1{##1}}%
- \dogetgroupargument\secondargumenttrue\secondargumentfalse}%
- \dogetgroupargument\firstargumenttrue\firstargumentfalse}
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
\def\dotriplegroupempty#1%
- {\def\dodogetargument##1%
- {\def\dodogetargument####1%
- {\def\dodogetargument%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested
{\dontpermitspacesbetweengroups
#1{##1}{####1}}%
- \dogetgroupargument\thirdargumenttrue\thirdargumentfalse}%
- \dogetgroupargument\secondargumenttrue\secondargumentfalse}%
- \dogetgroupargument\firstargumenttrue\firstargumentfalse}
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
\def\doquadruplegroupempty#1%
- {\def\dodogetargument##1%
- {\def\dodogetargument####1%
- {\def\dodogetargument########1%
- {\def\dodogetargument%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested########1%
+ {\def\syst_helpers_get_grouped_argument_nested
{\dontpermitspacesbetweengroups
#1{##1}{####1}{########1}}%
- \dogetgroupargument\fourthargumenttrue\fourthargumentfalse}%
- \dogetgroupargument\thirdargumenttrue\thirdargumentfalse}%
- \dogetgroupargument\secondargumenttrue\secondargumentfalse}%
- \dogetgroupargument\firstargumenttrue\firstargumentfalse}
+ \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}%
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
\def\doquintuplegroupempty#1%
- {\def\dodogetargument##1%
- {\def\dodogetargument####1%
- {\def\dodogetargument########1%
- {\def\dodogetargument################1%
- {\def\dodogetargument%
+ {\def\syst_helpers_get_grouped_argument_nested##1%
+ {\def\syst_helpers_get_grouped_argument_nested####1%
+ {\def\syst_helpers_get_grouped_argument_nested########1%
+ {\def\syst_helpers_get_grouped_argument_nested################1%
+ {\def\syst_helpers_get_grouped_argument_nested
{\dontpermitspacesbetweengroups
#1{##1}{####1}{########1}{################1}}%
- \dogetgroupargument\fifthargumenttrue\fifthargumentfalse}%
- \dogetgroupargument\fourthargumenttrue\fourthargumentfalse}%
- \dogetgroupargument\thirdargumenttrue\thirdargumentfalse}%
- \dogetgroupargument\secondargumenttrue\secondargumentfalse}%
- \dogetgroupargument\firstargumenttrue\firstargumentfalse}
+ \syst_helpers_get_grouped_argument\fifthargumenttrue\fifthargumentfalse}%
+ \syst_helpers_get_grouped_argument\fourthargumenttrue\fourthargumentfalse}%
+ \syst_helpers_get_grouped_argument\thirdargumenttrue\thirdargumentfalse}%
+ \syst_helpers_get_grouped_argument\secondargumenttrue\secondargumentfalse}%
+ \syst_helpers_get_grouped_argument\firstargumenttrue\firstargumentfalse}
%D These macros can explictly take care of spaces, which means
%D that the next definition and calls are valid:
@@ -2857,7 +2890,7 @@
%D nesting is to be expected, we can reuse \type{\wait} within
%D \type{\wait} itself.
-\def\wait
+\unexpanded\def\wait
{\begingroup
\read16 to \wait
\endgroup}
@@ -2888,24 +2921,24 @@
\newtoks\everywritestring
- \def\writedirect {\immediate\write\statuswrite}
- \def\writeline {\writedirect{}}
- \def\writestring#1{\begingroup\the\everywritestring\writedirect{#1}\endgroup}
+ \def\writedirect {\immediate\write\statuswrite}
+ \def\writeline {\writedirect{}}
+ \unexpanded\def\writestring#1{\begingroup\the\everywritestring\writedirect{#1}\endgroup}
\fi
-\def\normalwritestatus#1#2%
- {\writestring{\expandafter\dosplitstatus\expandafter\statuswidth#1%
+\unexpanded\def\normalwritestatus#1#2%
+ {\writestring{\expandafter\syst_helpers_split_status_yes\expandafter\statuswidth#1%
\space\space\space\space\space\space\space
\space\space\space\space\space\space\space
\space\space\space\space\space\space\end
\space:\space#2}}
-\def\dosplitstatus#1#2%
- {\ifcase#1 \expandafter\nosplitstatus\fi#2%
- \expandafter\dosplitstatus\expandafter{\the\numexpr#1+\minusone\relax}}
+\def\syst_helpers_split_status_yes#1#2%
+ {\ifcase#1 \expandafter\syst_helpers_split_status_nop\fi#2%
+ \expandafter\syst_helpers_split_status_yes\expandafter{\the\numexpr#1+\minusone\relax}}
-\def\nosplitstatus#1\end
+\def\syst_helpers_split_status_nop#1\end
{}
%D \macros
@@ -2925,13 +2958,13 @@
\newif\ifdebuggerinfo
-\def\debuggerinfo#1#2%
+\unexpanded\def\debuggerinfo#1#2%
{\ifdebuggerinfo
\writestatus{debugger}{#1:: #2}%
\fi}
-\ifdefined\writestatus \else \let\writestatus\normalwritestatus \fi
-\ifdefined\writebanner \else \def\writebanner{\writestring} \fi
+\ifdefined\writestatus \else \let\writestatus\normalwritestatus \fi
+\ifdefined\writebanner \else \unexpanded\def\writebanner{\writestring} \fi
% % % % % % % % % % % % % % % % % % % % % % % %
@@ -2941,13 +2974,13 @@
%D A raw and dirty alternative for \type {\getparameters}; no
%D checking is done!
-\def\rawsetparameter#1=#2,%
+\unexpanded\def\rawsetparameter#1=#2,%
{\if]#1\else
\expandafter\def\csname\rawparameterprefix#1\endcsname{#2}%
\expandafter\rawsetparameter
\fi}
-\def\rawgetparameters[#1][#2% some 5-10% faster
+\unexpanded\def\rawgetparameters[#1][#2% some 5-10% faster
{\ifx#2]% test is needed, else bomb on [#1][]
\expandafter\gobbleoneargument
\else
@@ -2970,28 +3003,28 @@
%D \type {\redoglobal}. When using only alternatives, one can
%D reset this mechanism with \type {\resetglobal}.
-\def\resetglobal
+\unexpanded\def\resetglobal
{\let\redoglobal\relax
\let\dodoglobal\relax}
\resetglobal
-\def\doglobal
+\unexpanded\def\doglobal
{\ifx\redoglobal\relax
\let\redoglobal\global
- \let\dodoglobal\@@dodoglobal
+ \let\dodoglobal\syst_helpers_dodo_global
\fi}
-\def\@@dodoglobal
+\def\syst_helpers_dodo_global
{\resetglobal\global}
\def\saveglobal
- {\let\@@dodoglobal\dodoglobal
- \let\@@redoglobal\redoglobal}
+ {\let\syst_helpers_dodo_global\dodoglobal
+ \let\syst_helpers_redo_global\redoglobal}
\def\restoreglobal
- {\let\redoglobal\@@redoglobal
- \let\dodoglobal\@@dodoglobal}
+ {\let\redoglobal\syst_helpers_redo_global
+ \let\dodoglobal\syst_helpers_dodo_global}
%D A very useful application of this macro is \type {\newif},
%D \TEX's fake boolean type. Not being a primitive,
@@ -3034,7 +3067,7 @@
\unexpanded\expandafter\def
\fi#1}
-\def\redefine#1%
+\unexpanded\def\redefine#1%
{\ifdefined#1%
\message{[\noexpand#1is redefined]}%
\fi
@@ -3062,76 +3095,46 @@
%
% [\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%
+\global\let\stoptexdefinition\relax
+
+\unexpanded\gdef\starttexdefinition%
{\bgroup%
\obeylines%
- \dostarttexdefinition}
+ \syst_helpers_start_tex_definition}
-\gdef\dostarttexdefinition #1
+\gdef\syst_helpers_start_tex_definition #1
{\catcode\endoflineasciicode\ignorecatcode%
- \doifinstringelse\letterhash{\detokenize{#1}}\dodostarttexdefinition\nonostarttexdefinition#1
+ \doifinstringelse\letterhash{\detokenize{#1}}\syst_helpers_start_tex_definition_yes\syst_helpers_start_tex_definition_nop#1
}
-\gdef\dodostarttexdefinition#1 #2
+\gdef\syst_helpers_start_tex_definition_yes#1 #2
{\edef\texdefinitionname{#1}%
\ifx\texdefinitionname\s!unexpanded%
- \expandafter\dododostarttexdefinitionU%
+ \expandafter\syst_helpers_start_tex_definition_yes_unexpanded%
\else%
- \expandafter\dododostarttexdefinitionN%
+ \expandafter\syst_helpers_start_tex_definition_yes_normal%
\fi%
{#1}#2
}
-\gdef\dododostarttexdefinitionU#1#2 #3
+\gdef\syst_helpers_start_tex_definition_yes_unexpanded#1#2 #3
#4\stoptexdefinition%
{\egroup% #1=unexpanded
\unexpanded\expandafter\def\csname#2\endcsname#3{#4}}
-\gdef\dododostarttexdefinitionN#1#2
+\gdef\syst_helpers_start_tex_definition_yes_normal#1#2
#3\stoptexdefinition%
{\egroup%
\expandafter\def\csname#1\endcsname#2{#3}}
-\gdef\nonostarttexdefinition#1
- {\nononostarttexdefinition{#1}{}}
+\gdef\syst_helpers_start_tex_definition_nop#1
+ {\syst_helpers_start_tex_definition_nop_indeed{#1}{}}
-\gdef\nononostarttexdefinition#1#2#3\stoptexdefinition%
+\gdef\syst_helpers_start_tex_definition_nop_indeed#1#2#3\stoptexdefinition%
{\egroup%
\expandafter\def\csname#1\endcsname{#3}}
@@ -3141,8 +3144,8 @@
% This is a first variant, more might be added:
-\def\starttexcode{\unprotect}
-\def\stoptexcode {\protect}
+\unexpanded\def\starttexcode{\unprotect}
+\unexpanded\def\stoptexcode {\protect}
%D \macros
%D {newcounter,
@@ -3202,7 +3205,7 @@
\def\zerocountervalue{0}
-\def\newcounter#1%
+\unexpanded\def\newcounter#1%
{\dodoglobal\let#1\zerocountervalue}
%D Nowadays we don't mind a few more tokens if we can gain a
@@ -3217,14 +3220,14 @@
\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}}
+\unexpanded\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}}
+\unexpanded\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}}
-\def\increment{\doifnextcharelse(\syst_helpers_do_do_increment\syst_helpers_do_increment}
-\def\decrement{\doifnextcharelse(\syst_helpers_do_do_decrement\syst_helpers_do_decrement}
+\unexpanded\def\increment{\doifnextcharelse(\syst_helpers_do_do_increment\syst_helpers_do_increment}
+\unexpanded\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}
+\unexpanded\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname}
+\unexpanded\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname}
%D \macros
%D {newsignal}
@@ -3245,9 +3248,9 @@
\newdimen\maximumsignal % step is about 0.00025pt
-\def\newsignal#1%
+\unexpanded\def\newsignal#1%
{\ifdefined#1\else
- \advance\maximumsignal 2sp % to be save in rounding
+ \advance\maximumsignal 2\scaledpoint % to be save in rounding
\edef#1{\the\maximumsignal}%
\fi}
@@ -3262,9 +3265,9 @@
%D \stoptyping
\def\checkedstrippedcsname#1% this permits \strippedcsname{\xxx} and \strippedcsname{xxx}
- {\expandafter\docheckedstrippedcsname\string#1}
+ {\expandafter\syst_helpers_checked_stripped_csname\string#1}
-\def\docheckedstrippedcsname#1%
+\def\syst_helpers_checked_stripped_csname#1%
{\if\noexpand#1\letterbackslash\else#1\fi}
%D \macros
@@ -3272,15 +3275,14 @@
%D
%D We will use this one in:
-\def\savenormalmeaning#1%
+\unexpanded\def\savenormalmeaning#1%
{\ifcsname normal\strippedcsname#1\endcsname \else
- \letvalue{normal\strippedcsname#1}#1%
+ \expandafter\let\csname normal\strippedcsname#1\endcsname#1%
\fi}
%D \macros
%D {dorecurse,recurselevel,recursedepth,
-%D dostepwiserecurse,
-%D for}
+%D dostepwiserecurse}
%D
%D \TEX\ does not offer us powerfull for||loop mechanisms. On
%D the other hand its recursion engine is quite unique. We
@@ -3326,77 +3328,79 @@
\def\recursedepth{\the\outerrecurse}
\def\recurselevel{0}
-\let\nextrecurse\relax
+\let\syst_helpers_stepwise_next\relax
-\def\@@irecurse{@@ir@@} % ecurse} % stepper
-\def\@@arecurse{@@ar@@} % ecurse} % action
+\installsystemnamespace{recurseindex}
+\installsystemnamespace{recurseaction}
\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
{\global\advance\outerrecurse \plusone
- \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname{#4}%
- \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \ifnum#3>0\relax
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname{#4}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \ifnum#3>\zerocount\relax
\ifnum#2<#1\relax
- \let\nextrecurse\exitstepwiserecurse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
\else
- \let\nextrecurse\dodostepwiserecurse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse
\fi
\else
- \ifnum#3<0\relax
+ \ifnum#3<\zerocount\relax
\ifnum#1<#2\relax
- \let\nextrecurse\exitstepwiserecurse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
\else
- \let\nextrecurse\dodostepwisereverse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse
\fi
\else
- \let\nextrecurse\exitstepwiserecurse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
\fi
- \fi\normalexpanded{\nextrecurse{\number#1}{\number#2}{\number#3}}}
+ \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}}
-\def\dodostepwiserecurse#1#2#3% from to step
+\unexpanded\def\syst_helpers_stepwise_recurse#1#2#3% from to step
{\ifnum#1>#2\relax
- \expandafter\nodostepwiserecurse
+ \expandafter\syst_helpers_stepwise_recurse_nop
\else
\def\recurselevel{#1}%
- \doubleexpandafter\redostepwiserecurse\expandafter
+ \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter
\fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
-\unexpanded\def\expandrecursecontent
- {\csname\@@arecurse\recursedepth\endcsname}
+\unexpanded\def\syst_helpers_recurse_content
+ {\csname\??recurseaction\recursedepth\endcsname}
-\unexpanded\def\redostepwiserecurse
- {\expandrecursecontent\dodostepwiserecurse}
+\unexpanded\def\syst_helpers_stepwise_recurse_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_stepwise_recurse}
-\unexpanded\def\dodostepwisereverse#1#2#3% from to step
+\unexpanded\def\syst_helpers_stepwise_reverse#1#2#3% from to step
{\ifnum#1<#2\relax
- \expandafter\nodostepwiserecurse
+ \expandafter\syst_helpers_stepwise_recurse_nop
\else
\def\recurselevel{#1}%
\innerrecurse#1\relax
\advance\innerrecurse#3\relax
- \doubleexpandafter\redostepwisereverse\expandafter
+ \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter
\fi\expandafter{\the\innerrecurse}{#2}{#3}}
-\unexpanded\def\redostepwisereverse
- {\expandrecursecontent\dodostepwisereverse}
+\unexpanded\def\syst_helpers_stepwise_reverse_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_stepwise_reverse}
-\unexpanded\def\exitstepwiserecurse
- {\nodostepwiserecurse\relax}
+\unexpanded\def\syst_helpers_stepwise_exit
+ {\syst_helpers_stepwise_recurse_nop\relax}
-\unexpanded\def\nodostepwiserecurse#1#2#3#4%
- {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
- \global\advance\outerrecurse \minusone}
+\unexpanded\def\syst_helpers_stepwise_recurse_nop#1#2#3#4%
+ {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ \global\advance\outerrecurse\minusone}
-\unexpanded\def\nonostepwiserecurse#1#2#3%
- {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
- \global\advance\outerrecurse \minusone}
+% \unexpanded\def\nonostepwiserecurse#1#2#3%
+% {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+% \global\advance\outerrecurse\minusone}
\unexpanded\def\dorecurse#1%
- {\dostepwiserecurse1{#1}1}
+ {\dostepwiserecurse\plusone{#1}\plusone}
-\def\doexpandedrecurse#1#2%
+\def\doexpandedrecurse#1#2% user macro (also was \doxprecurse)
{\ifnum#1>\zerocount
- #2\expandafter\doexpandedrecurse\expandafter{\the\numexpr#1-1\relax}{#2}%
+ #2\expandafter\doexpandedrecurse\expandafter{\the\numexpr#1-\plusone\relax}{#2}%
\fi}
%D As we can see here, the simple command \type{\dorecurse} is
@@ -3422,47 +3426,48 @@
{\ifcase#1\relax
\expandafter\gobbletwoarguments
\or
- \expandafter\ydorecurse
+ \expandafter\syst_helpers_recurse_y
\else
- \expandafter\xdorecurse
+ \expandafter\syst_helpers_recurse_x
\fi{#1}}
-\unexpanded\def\xdorecurse#1#2%
+\unexpanded\def\syst_helpers_recurse_x#1#2%
{\global\advance\outerrecurse \plusone
- \expandafter\gdef\csname\@@arecurse\recursedepth\endcsname{#2}%
- \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \expandafter\dodorecurse\expandafter1\expandafter{\number#1}}
+ \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#2}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}}
-\unexpanded\def\ydorecurse#1#2%
+\unexpanded\def\syst_helpers_recurse_y#1#2%
{\global\advance\outerrecurse \plusone
- \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
\let\recurselevel\!!plusone
#2%
- \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
\global\advance\outerrecurse \minusone}
-\unexpanded\def\dodorecurse#1#2% from to
+\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to
{\ifnum#1>#2\relax
- \expandafter\nodorecurse
+ \expandafter\syst_helpers_recurse_indeed_nop
\else
\def\recurselevel{#1}%
- \doubleexpandafter\redorecurse
+ \doubleexpandafter\syst_helpers_recurse_indeed_yes
\fi\expandafter{\the\numexpr\recurselevel+\plusone\relax}{#2}}
-\unexpanded\def\dodorecurse#1#2% from to
+\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to
{\ifnum#1>#2\relax
- \expandafter\nodorecurse
+ \expandafter\syst_helpers_recurse_indeed_nop
\else
\def\recurselevel{#1}%
\innerrecurse#1\advance\innerrecurse\plusone
- \doubleexpandafter\redorecurse
+ \doubleexpandafter\syst_helpers_recurse_indeed_yes
\fi\expandafter{\the\innerrecurse}{#2}}
-\unexpanded\def\redorecurse
- {\expandrecursecontent\dodorecurse}
+\unexpanded\def\syst_helpers_recurse_indeed_yes
+ {\syst_helpers_recurse_content
+ \syst_helpers_recurse_indeed}
-\unexpanded\def\nodorecurse#1#2#3%
- {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
+\unexpanded\def\syst_helpers_recurse_indeed_nop#1#2#3%
+ {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
\global\advance\outerrecurse \minusone }
%D \macros
@@ -3483,32 +3488,33 @@
%D When needed, one can call for \type{\looplevel} and
%D \type{\loopdepth}.
-\let\endofloop\donothing
+\let\endofloop\donothing % maybe \syst_helpers_loop_end
\unexpanded\def\doloop#1%
{\global\advance\outerrecurse \plusone
- \expandafter\gdef\csname\@@arecurse\recursedepth\endcsname{#1}%
- \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \let\endofloop\dodoloop
- \dodoloop1} % no \plusone else \recurselevel wrong
+ \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#1}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \let\endofloop\syst_helpers_loop
+ \syst_helpers_loop1} % no \plusone else \recurselevel wrong
-\unexpanded\def\dodoloop#1%
+\unexpanded\def\syst_helpers_loop#1%
{\def\recurselevel{#1}%
- \expandafter\redoloop\expandafter{\the\numexpr\recurselevel+\plusone\relax}}
+ \expandafter\syst_helpers_loop_yes\expandafter{\the\numexpr\recurselevel+\plusone\relax}}
-\unexpanded\def\redoloop
- {\expandrecursecontent\endofloop}
+\unexpanded\def\syst_helpers_loop_yes
+ {\syst_helpers_recurse_content
+ \endofloop}
-\unexpanded\def\nodoloop#1%
- {\let\endofloop\dodoloop % new, permits nested \doloop's
- \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
+\unexpanded\def\syst_helpers_loop_nop#1%
+ {\let\endofloop\syst_helpers_loop % new, permits nested \doloop's
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
\global\advance\outerrecurse\minusone}
\unexpanded\def\exitloop % \exitloop quits at end
- {\let\endofloop\nodoloop}
+ {\let\endofloop\syst_helpers_loop_nop}
\unexpanded\def\exitloopnow#1\endofloop % \exitloopnow quits directly
- {\nodoloop}
+ {\syst_helpers_loop_nop}
%D The loop is executed at least once, so beware of situations
%D like:
@@ -3548,94 +3554,113 @@
%D \dorecurse{3}{\expanded{\definesymbol[test-\recurselevel][xx-\recurselevel]}}
%D \stoptyping
-\def\expandrecursecontent
- {\csname\@@arecurse\recursedepth\expandafter\expandafter\expandafter\endcsname
+\def\syst_helpers_recurse_content
+ {\csname\??recurseaction\recursedepth\expandafter\expandafter\expandafter\endcsname
\expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\recursedepth}}
-\unexpanded\def\xdorecurse#1#2%
+\unexpanded\def\syst_helpers_recurse_x#1#2%
{\global\advance\outerrecurse \plusone
- \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}%
- \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \expandafter\dodorecurse\expandafter1\expandafter{\number#1}}
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}}
-\unexpanded\def\ydorecurse#1#2%
+\unexpanded\def\syst_helpers_recurse_y#1#2%
{\global\advance\outerrecurse \plusone
- \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
\let\recurselevel\!!plusone
- \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}%
- \expandrecursecontent
- \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}%
+ \syst_helpers_recurse_content
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
\global\advance\outerrecurse \minusone}
\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
{\global\advance\outerrecurse \plusone
- \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
- \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \ifnum#3>0\relax
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \ifnum#3>\zerocount\relax
\ifnum#2<#1\relax
- \let\nextrecurse\exitstepwiserecurse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
\else
- \let\nextrecurse\dodostepwiserecurse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse
\fi
\else
- \ifnum#3<0\relax
+ \ifnum#3<\zerocount\relax
\ifnum#1<#2\relax
- \let\nextrecurse\exitstepwiserecurse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
\else
- \let\nextrecurse\dodostepwisereverse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse
\fi
\else
- \let\nextrecurse\exitstepwiserecurse
+ \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
\fi
- \fi\normalexpanded{\nextrecurse{\number#1}{\number#2}{\number#3}}}
+ \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}}
\unexpanded\def\doloop#1%
{\global\advance\outerrecurse \plusone
- \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
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#1}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \let\endofloop\syst_helpers_loop
+ \syst_helpers_loop1} % no \plusone else \recurselevel wrong
% faster
+% \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+% {\global\advance\outerrecurse \plusone
+% \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}%
+% \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+% \csname @swr%
+% \ifnum#3>\zerocount
+% \ifnum#2<#1\else d\fi
+% \else\ifnum#3<\zerocount
+% \ifnum#1<#2\else r\fi
+% \fi\fi
+% \expandafter\endcsname\normalexpanded{{\number#1}{\number#2}{\number#3}}}
+
+% \let\@swr \syst_helpers_stepwise_exit
+% \let\@swrd\syst_helpers_stepwise_recurse
+% \let\@swrr\syst_helpers_stepwise_reverse
+
+\installsystemnamespace{recursestepwise}
+
\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
{\global\advance\outerrecurse \plusone
- \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
- \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \csname @swr%
+ \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}%
+ \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \csname\??recursestepwise
\ifnum#3>\zerocount
\ifnum#2<#1\else d\fi
\else\ifnum#3<\zerocount
\ifnum#1<#2\else r\fi
\fi\fi
\expandafter\endcsname\normalexpanded{{\number#1}{\number#2}{\number#3}}}
+ % \expandafter\endcsname\expandafter{\number#1\expandafter}\expandafter{\number#2\expandafter}\expandafter{\number#3}}
-\let\@swr \exitstepwiserecurse
-\let\@swrd\dodostepwiserecurse
-\let\@swrr\dodostepwisereverse
+\letvalue{\??recursestepwise }\syst_helpers_stepwise_exit
+\letvalue{\??recursestepwise d}\syst_helpers_stepwise_recurse
+\letvalue{\??recursestepwise r}\syst_helpers_stepwise_reverse
% quite okay too, but untested
%
% \def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
% {\global\advance\outerrecurse \plusone
-% \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
-% \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+% \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#4}%
+% \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
% \normalexpanded
% {\ifnum#3>\zerocount
% \ifnum#2<#1
-% \exitstepwiserecurse
+% \syst_helpers_stepwise_exit
% \else
-% \dodostepwiserecurse
+% \syst_helpers_stepwise_recurse
% \fi
% \else
% \ifnum#3<\zerocount
% \ifnum#1<#2
-% \exitstepwiserecurse
+% \syst_helpers_stepwise_exit
% \else
-% \dodostepwisereverse
+% \syst_helpers_stepwise_reverse
% \fi
% \else
-% \exitstepwiserecurse
+% \syst_helpers_stepwise_exit
% \fi
% \fi{\number#1}{\number#2}{\number#3}}}
@@ -3643,21 +3668,22 @@
\newcount\fastloopindex
\newcount\fastloopfinal
-\let\fastloopcs\relax
+
+\let\m_syst_helpers_fast_loop_cs\relax
\unexpanded\def\dofastloopcs#1#2%
- {\let\fastloopcs#2
+ {\let\m_syst_helpers_fast_loop_cs#2%
\fastloopindex\plusone
\fastloopfinal#1\relax
- \dodofastloopcs}
+ \syst_helpers_fast_loop_cs}
-\unexpanded\def\dodofastloopcs
+\unexpanded\def\syst_helpers_fast_loop_cs
{\ifnum\fastloopindex>\fastloopfinal
- \let\fastloopcs\relax
+ \let\m_syst_helpers_fast_loop_cs\relax
\else
- \fastloopcs
+ \m_syst_helpers_fast_loop_cs
\advance\fastloopindex\plusone
- \expandafter\dodofastloopcs
+ \expandafter\syst_helpers_fast_loop_cs
\fi}
% Helper:
@@ -3693,10 +3719,10 @@
\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
+ \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname##1{\edef\recursestring{##1}#2}%
+ \expandafter\glet\csname\??recurseindex\recursedepth\endcsname\recursestring
+ \normalexpanded{\processcommalist[#1]{\expandafter\noexpand\csname\??recurseaction\recursedepth\endcsname}}%
+ \expandafter\let\expandafter\recursestring\csname\??recurseindex\recursedepth\endcsname
\global\advance\outerrecurse\minusone}
%D \macros
@@ -3724,20 +3750,20 @@
% \EveryPar{y } \everypar{before } [before] \par
% }
-% retrofit this into mkii
-
-\def\dowithevery#1%
- {\expandafter\removetoks\expandafter\the\csname t\strippedcsname#1\endcsname\from#1%
- \expandafter\appendtoks\expandafter\the\csname t\strippedcsname#1\endcsname\to #1%
- \csname t\strippedcsname#1\endcsname}
+\installsystemnamespace{extraevery}
-\def\newevery#1#2%
+\unexpanded\def\newevery#1#2%
{\ifx#1\everypar\else\newtoks#1\fi% we test for redefinition elsewhere
\ifx#2\relax\else\ifdefined#2\else
- \expandafter\newtoks\csname t\strippedcsname#1\endcsname
- \def#2{\dowithevery#1}%
+ \expandafter\newtoks\csname\??extraevery\strippedcsname#1\endcsname
+ \def#2{\syst_helpers_every#1}%
\fi\fi}
+\unexpanded\def\syst_helpers_every#1%
+ {\expandafter\removetoks\expandafter\the\csname\??extraevery\strippedcsname#1\endcsname\from#1%
+ \expandafter\appendtoks\expandafter\the\csname\??extraevery\strippedcsname#1\endcsname\to #1%
+ \csname\??extraevery\strippedcsname#1\endcsname}
+
%D This one permits definitions like:
\newevery \everypar \EveryPar % we get a warning which is ok
@@ -3745,7 +3771,23 @@
%D and how about:
-\newevery \neverypar \NeveryPar
+% \newtoks \neverypar
+% \newtoks \neveryendpar
+%
+% \normalprotected\def\syst_helpers_forgotten_endpar
+% {\the\neveryendpar\normalpar}
+%
+% \unexpanded\def\forgeteverypar
+% {\everypar{\the\neverypar}%
+% \let\endpar\syst_helpers_forgotten_endpar}
+%
+% \unexpanded\def\finishpar
+% {\ifvmode\else\par\fi}
+
+\newtoks \neverypar
+
+\unexpanded\def\forgeteverypar
+ {\everypar{\the\neverypar}}
%D Which we're going to use indeed! When the second argument
%D equals \type {\relax}, the first token list is created
@@ -3817,10 +3859,10 @@
%D Both commands accept the prefix \type{\doglobal} for global
%D assignments.
-\def\convertvalue#1\to
+\unexpanded\def\convertvalue#1\to
{\expandafter\convertcommand\csname#1\endcsname\to}
-\def\defconvertedvalue#1#2% less sensitive for \to
+\unexpanded\def\defconvertedvalue#1#2% less sensitive for \to
{\expandafter\defconvertedcommand\expandafter#1\csname#2\endcsname}
%D \macros
@@ -3843,10 +3885,10 @@
%D \doifassignmentelse {...} {then ...} {else ...}
%D \stoptyping
-\def\docheckifassignmentelse#1=#2#3\@end@{\if#2@}%
+\def\syst_helpers_check_if_assignment_else#1=#2#3\_e_o_p_{\if#2@}%
-\def\doifassignmentelse#1% expandable
- {\expandafter\docheckifassignmentelse\detokenize{#1}=@@\@end@
+\unexpanded\def\doifassignmentelse#1% expandable
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
@@ -3854,23 +3896,12 @@
\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
-% D Sometimes we need to convert an argument to a string (letters
-% D only), for instance when we compare it with another string:
-% D
-% D \starttyping
-% D \convertasciiafter\doifinstringelse{em}{\ascii}{...}
-% D \stoptyping
-%
-% \def\convertasciiafter#1#2%
-% {\expandafter#1\expandafter{\detokenize{#2}}}
+\unexpanded\def\docheckassignment#1%
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_
+ \assignmentfalse
+ \else
+ \assignmenttrue
+ \fi}
%D In \ETEX\ we can use \type {\detokenize} and gain some
%D speed, but in general far less that 1\% for \type
@@ -3879,17 +3910,17 @@
%D something I found out when primitives like \type
%D {\jobname} were fed (or something undefined).
-\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
+\unexpanded\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}}
+\unexpanded\def\convertcommand #1\to#2{\dodoglobal\edef#2{\expandafter\detokenize\expandafter{#1}}} % hm, only second is also ok
-\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}}}
+\unexpanded\def\defconvertedargument #1#2{\edef#1{\detokenize{#2}}}
+\unexpanded\def\defconvertedcommand #1#2{\edef#1{\detokenize\expandafter{#2}}}
+\unexpanded\def\edefconvertedargument#1#2{\edef#1{#2}%
+ \edef#1{\detokenize\expandafter{#1}}}
+\unexpanded\def\gdefconvertedargument#1#2{\xdef#1{\detokenize{#2}}}
+\unexpanded\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\expandafter{#2}}}
+\unexpanded\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
@@ -3910,14 +3941,11 @@
%D argument are completely redundant.
%D \macros
-%D {showvalue,showargument}
+%D {showvalue}
%D
-%D Two handy macros for testing purposes only:
-
-\def\showvalue#1%
- {\expandafter\show\csname#1\endcsname}
+%D Ahandy macro, for testing purposes only:
-\def\showvalue#1%
+\unexpanded\def\showvalue#1%
{\ifcsname#1\endcsname
\expandafter\show\csname#1\endcsname
\else
@@ -3938,11 +3966,11 @@
%D
%D Watch the one level expansion of the second argument.
-\def\doifmeaningelse#1#2%
- {\edef\!!stringa{\meaning#1}%
- \def \!!stringb{#2}%
- \edef\!!stringb{\meaning\!!stringb}%
- \ifx\!!stringa\!!stringb
+\unexpanded\def\doifmeaningelse#1#2%
+ {\edef\m_syst_string_one{\meaning#1}%
+ \def \m_syst_string_two{#2}%
+ \edef\m_syst_string_two{\meaning\m_syst_string_two}%
+ \ifx\m_syst_string_one\m_syst_string_two
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
@@ -3960,14 +3988,14 @@
%D \doifsamestringelse{\jobname}{oeps}{YES}{NO}
%D \stoptyping
-\def\@@doifsamestringelse#1#2#3#4%
- {\edef\!!stringa{\detokenize\expandafter{\normalexpanded{#3}}}%
- \edef\!!stringb{\detokenize\expandafter{\normalexpanded{#4}}}%
- \ifx\!!stringa\!!stringb\expandafter#1\else\expandafter#2\fi}
+\def\syst_helpers_if_samestring_else#1#2#3#4%
+ {\edef\m_syst_string_one{\detokenize\expandafter{\normalexpanded{#3}}}%
+ \edef\m_syst_string_two{\detokenize\expandafter{\normalexpanded{#4}}}%
+ \ifx\m_syst_string_one\m_syst_string_two\expandafter#1\else\expandafter#2\fi}
-\def\doifsamestringelse{\@@doifsamestringelse\firstoftwoarguments\secondoftwoarguments}
-\def\doifsamestring {\@@doifsamestringelse\firstofoneargument \gobbleoneargument }
-\def\doifnotsamestring {\@@doifsamestringelse\gobbleoneargument \firstofoneargument }
+\unexpanded\def\doifsamestringelse{\syst_helpers_if_samestring_else\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifsamestring {\syst_helpers_if_samestring_else\firstofoneargument \gobbleoneargument }
+\unexpanded\def\doifnotsamestring {\syst_helpers_if_samestring_else\gobbleoneargument \firstofoneargument }
%D \macros
%D {ConvertToConstant,ConvertConstantAfter}
@@ -3995,10 +4023,10 @@
%D In examples~2 and~3 both arguments equal, in~1 and~4
%D they differ.
-\def\ConvertToConstant#1#2#3%
- {\edef\!!stringa{\expandafter\detokenize\expandafter{#2}}%
- \edef\!!stringb{\expandafter\detokenize\expandafter{#3}}%
- #1{\!!stringa}{\!!stringb}}
+\unexpanded\def\ConvertToConstant#1#2#3%
+ {\edef\m_syst_string_one{\expandafter\detokenize\expandafter{#2}}%
+ \edef\m_syst_string_two{\expandafter\detokenize\expandafter{#3}}%
+ #1{\m_syst_string_one}{\m_syst_string_two}}
%D When the argument \type{#1} consists of commands, we had
%D better use
@@ -4027,14 +4055,14 @@
%D
%D where \type{...} can be anything legally \TEX.
-\def\CheckConstantAfter#1#2%
+\unexpanded\def\CheckConstantAfter#1#2%
{\expandafter\convertargument\v!prefix!\to\ascii
\convertargument#1\to#2\relax
\doifinstringelse\ascii{#2}
{\expandafter\convertargument#1\to#2}
{}}
-\def\ConvertConstantAfter#1#2#3%
+\unexpanded\def\ConvertConstantAfter#1#2#3%
{\CheckConstantAfter{#2}\asciia
\CheckConstantAfter{#3}\asciib
#1{\asciia}{\asciib}}
@@ -4050,7 +4078,7 @@
%D
%D We don't explicitly test if the macro is defined.
-\def\assignifempty#1#2% can be sped up
+\unexpanded\def\assignifempty#1#2% can be sped up
{\doifsomething{#1}{\def#1{#2}}} % {\doifnot{#1}{}{\def#1{#2}}}
%D \macros
@@ -4094,11 +4122,13 @@
%D
%D results in: \type{\message{Hello world!}}.
-\def\dograbuntil#1#2%
- {\def\next##1#1{#2{##1}}\next}
+\let\syst_helpers_grab_indeed\relax
-\def\grabuntil#1%
- {\expandafter\dograbuntil\expandafter{\csname#1\endcsname}}
+\unexpanded\def\syst_helpers_grab#1#2%
+ {\def\syst_helpers_grab_indeed##1#1{#2{##1}}\syst_helpers_grab_indeed}
+
+\unexpanded\def\grabuntil#1%
+ {\expandafter\syst_helpers_grab\expandafter{\csname#1\endcsname}}
%D The next command build on this mechanism:
%D
@@ -4122,13 +4152,15 @@
%D is related to these commands. This one simply throws away
%D everything preceding \type{\command}.
-\def\processbetween#1#2%
+\let\syst_helpers_gobble_indeed\relax
+
+\unexpanded\def\processbetween#1#2%
{\setvalue{\s!start#1}{\grabuntil{\s!stop#1}{#2}}}
-\def\gobbleuntil#1%
- {\def\next##1#1{}\next}
+\unexpanded\def\gobbleuntil#1%
+ {\def\syst_helpers_gobble_indeed##1#1{}\syst_helpers_gobble_indeed}
-\def\gobbleuntilrelax#1\relax
+\unexpanded\def\gobbleuntilrelax#1\relax
{}
%D The next one simply expands the pickup up tokens.
@@ -4137,8 +4169,10 @@
%D \processuntil{sequence}
%D \stoptyping
-\def\processuntil#1%
- {\def\next##1#1{##1}\next}
+\let\syst_helpers_until_indeed\relax
+
+\unexpanded\def\processuntil#1%
+ {\def\syst_helpers_until_indeed##1#1{##1}\syst_helpers_until_indeed}
%D \macros
%D {groupedcommand}
@@ -4183,7 +4217,7 @@
%D
%D \starttyping
%D \def\rightword%
-%D {\groupedcommand{\hfill\hbox}{\parfillskip\!!zeropoint}}
+%D {\groupedcommand{\hfill\hbox}{\parfillskip\zeropoint}}
%D
%D .......... \rightword{the right way}
%D \stoptyping
@@ -4202,45 +4236,85 @@
%D to be {\bold bold} or not, that's the question
%D \stoptyping
%D
-%D This alternative checks for a \type{\bgroup} token first.
-%D The internal alternative does not accept the box handling
-%D mentioned before, but further nesting works all right. The
-%D extra \type{\bgroup}||\type{\egroup} is needed to keep
-%D \type{\AfterGroup} both into sight and local.
+%D This alternative checks for a \type {\bgroup} token first. The internal
+%D alternative does not accept the box handling mentioned before, but further
+%D nesting works all right. The extra \type {\bgroup}||\type {\egroup} is needed to
+%D keep \type {\m_syst_helpers_handle_group_after} both into sight and local.
+
+\let\m_syst_helpers_handle_group_after \relax
+\let\m_syst_helpers_handle_group_before\relax
-\def\HandleGroup#1#2%
+% keep:
+%
+% \unexpanded\def\syst_helpers_handle_group_normal#1#2%
+% {\bgroup
+% \def\m_syst_helpers_handle_group_before{\bgroup#1\bgroup\aftergroup\m_syst_helpers_handle_group_after}% can't we remove the second \bgroup
+% \def\m_syst_helpers_handle_group_after {#2\egroup\egroup}% and one \egroup here?
+% \afterassignment\m_syst_helpers_handle_group_before
+% \let\next=}
+
+\unexpanded\def\syst_helpers_handle_group_normal#1#2%
{\bgroup
- \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
+ \def\m_syst_helpers_handle_group_before{#1}%
+ \def\m_syst_helpers_handle_group_after {#2}%
+ \afterassignment\m_syst_helpers_handle_group_normal_before
\let\next=}
-\def\HandleSimpleGroup#1#2% no inner group (so no kerning interference)
+\def\m_syst_helpers_handle_group_normal_before
{\bgroup
- %def\BeforeGroup{\bgroup#1\aftergroup\AfterGroup}% interferes
- \def\BeforeGroup{\bgroup\aftergroup\AfterGroup#1}%
- \def\AfterGroup {#2\egroup}%
- \afterassignment\BeforeGroup
+ \m_syst_helpers_handle_group_before
+ \bgroup
+ \aftergroup\m_syst_helpers_handle_group_normal_after}
+
+\def\m_syst_helpers_handle_group_normal_after
+ {\m_syst_helpers_handle_group_after
+ \egroup
+ \egroup}
+
+% keep:
+%
+% \unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference)
+% {\bgroup
+% %def\m_syst_helpers_handle_group_before{\bgroup#1\aftergroup\m_syst_helpers_handle_group_after}% interferes
+% \def\m_syst_helpers_handle_group_before{\bgroup\aftergroup\m_syst_helpers_handle_group_after#1}%
+% \def\m_syst_helpers_handle_group_after {#2\egroup}%
+% \afterassignment\m_syst_helpers_handle_group_before
+% \let\next=}
+
+\unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference)
+ {\bgroup
+ \def\m_syst_helpers_handle_group_before{#1}%
+ \def\m_syst_helpers_handle_group_after {#2}%
+ \afterassignment\m_syst_helpers_handle_group_simple_before
\let\next=}
-% \def\HandleNoGroup#1#2%
-% {\def\AfterGroup{#2\egroup}%
-% \bgroup\aftergroup\AfterGroup#1}
+\def\m_syst_helpers_handle_group_simple_before
+ {\bgroup
+ \aftergroup\m_syst_helpers_handle_group_simple_after
+ \m_syst_helpers_handle_group_before}
-\def\HandleNoGroup % retrofit into mkii
+\def\m_syst_helpers_handle_group_simple_after
+ {\m_syst_helpers_handle_group_after
+ \egroup}%
+
+\unexpanded\def\syst_helpers_handle_group_nop
{\ifnum\currentgrouptype=\semisimplegroupcode
- \expandafter\HandleNoGroupA
+ \expandafter\syst_helpers_handle_group_nop_a
\else
- \expandafter\HandleNoGroupB
+ \expandafter\syst_helpers_handle_group_nop_b
\fi}
-\def\HandleNoGroupA#1#2%
- {\def\AfterGroup{#2\endgroup}%
- \begingroup\aftergroup\AfterGroup#1}
+\def\syst_helpers_handle_group_nop_a#1#2%
+ {\def\m_syst_helpers_handle_group_after{#2\endgroup}%
+ \begingroup
+ \aftergroup\m_syst_helpers_handle_group_after
+ #1}
-\def\HandleNoGroupB#1#2%
- {\def\AfterGroup{#2\egroup}%
- \bgroup\aftergroup\AfterGroup#1}
+\def\syst_helpers_handle_group_nop_b#1#2%
+ {\def\m_syst_helpers_handle_group_after{#2\egroup}%
+ \bgroup
+ \aftergroup\m_syst_helpers_handle_group_after
+ #1}
%D I considered it a nuisance that
%D
@@ -4255,10 +4329,10 @@
%D implementation became:
\unexpanded\def\groupedcommand#1#2%
- {\doifnextbgroupelse{\HandleGroup{#1}{#2}}{\HandleNoGroup{#1}{#2}}}
+ {\doifnextbgroupelse{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}}
\unexpanded\def\simplegroupedcommand#1#2%
- {\doifnextbgroupelse{\HandleSimpleGroup{#1}{#2}}{\HandleNoGroup{#1}{#2}}}
+ {\doifnextbgroupelse{\syst_helpers_handle_group_simple{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}}
%D Users should be aware of the fact that grouping can
%D interfere with ones paragraph settings that are executed
@@ -4288,10 +4362,10 @@
%D \type{CAPITALS}. This suggestion is feasible, because
%D \CONTEXT only defines lowcased macros.
-\def\showdefinederror#1#2%
+\unexpanded\def\showdefinederror#1#2%
{\writestatus\m!system{#1 #2 replaces a macro, use CAPITALS!}}
-\def\checkdefined#1#2#3%
+\unexpanded\def\checkdefined#1#2#3%
{\doifdefined{#3}{\showdefinederror{#2}{#3}}}
%D \macros
@@ -4413,10 +4487,13 @@
%D ... \par
%D \stoptyping
+\let\syst_helpers_next_par\relax
+\let\syst_helpers_next_arg\relax
+
\unexpanded\def\dowithpargument#1%
- {\def\nextpar##1 \par{#1{##1}}%
- \def\nextarg##1{#1{##1}}%
- \doifnextbgroupelse\nextarg{\doifnextcharelse\par{#1{}}\nextpar}}
+ {\def\syst_helpers_next_par##1 \par{#1{##1}}%
+ \def\syst_helpers_next_arg##1{#1{##1}}%
+ \doifnextbgroupelse\syst_helpers_next_arg{\doifnextcharelse\par{#1{}}\syst_helpers_next_par}}
%D The \type{p} in the previous command stands for paragraph.
%D When we want to act upon words we can use the \type{w}
@@ -4440,10 +4517,13 @@
%D ...
%D \stoptyping
+\let\syst_helpers_next_war\relax
+\let\syst_helpers_next_arg\relax
+
\unexpanded\def\dowithwargument#1%
- {\def\nextwar##1 {#1{##1}}%
- \def\nextarg##1{#1{##1}}%
- \doifnextbgroupelse\nextarg\nextwar}
+ {\def\syst_helpers_next_war##1 {#1{##1}}%
+ \def\syst_helpers_next_arg##1{#1{##1}}%
+ \doifnextbgroupelse\syst_helpers_next_arg\syst_helpers_next_war}
%D \macros
%D {dorepeat,dorepeatwithcommand}
@@ -4476,12 +4556,12 @@
%D specification is missing, the command executes once.
\unexpanded\def\dorepeatwithcommand[#1]%
- {\dodorepeatwithcommand#1*\empty*\relax}
+ {\syst_helpers_repeat_with_command#1*\empty*\relax}
-\def\dodorepeatwithcommand#1*#2#3*#4\relax#5%
- {\ifx#2\empty\redorepeatwithcommand[#1]#5\else\dododorepeatwithcommand{#1}{#2}{#3}#5\fi}
+\def\syst_helpers_repeat_with_command#1*#2#3*#4\relax#5%
+ {\ifx#2\empty\syst_helpers_repeat_with_command_again[#1]#5\else\syst_helpers_repeat_with_command_indeed{#1}{#2}{#3}#5\fi}
-\def\dododorepeatwithcommand#1#2#3#4%
+\def\syst_helpers_repeat_with_command_indeed#1#2#3#4%
{\ifx#2\empty % redundant but gives cleaner extensions
#4{#1}%
\else\ifnum#1<\zerocount
@@ -4493,7 +4573,7 @@
\dorecurse{#1}{#4{#2#3}}%
\fi\fi\fi}
-\def\redorepeatwithcommand[#1]#2%
+\def\syst_helpers_repeat_with_command_again[#1]#2%
{#2{#1}}
%D The extension hook permits something like:
@@ -4503,11 +4583,11 @@
%D
%D \catcode`\*=\superscriptcatcode
%D
-%D \gdef\redorepeatwithcommand[#1]%
+%D \gdef\syst_helpers_repeat_with_command_again[#1]%
%D {\redodorepeatwithcommand#1*\empty*\relax}
%D
%D \gdef\redodorepeatwithcommand#1*#2#3*#4\relax#5%
-%D {\dododorepeatwithcommand{#1}{#2}{#3}#5}
+%D {\syst_helpers_repeat_with_command_indeed{#1}{#2}{#3}#5}
%D
%D \egroup
%D \stoptyping
@@ -4515,14 +4595,6 @@
%D although one may wonder if changing the catcode of \type {*} is wise.
%D \macros
-%D {normalbgroup,normalgroup}
-%D
-%D No comment.
-
-\let\normalbgroup\bgroup
-\let\normalegroup\egroup
-
-%D \macros
%D {doifstringinstringelse}
%D
%D The next macro is meant for situations where both strings
@@ -4539,7 +4611,7 @@
%D
%D A bit faster is:
-\def\pp!doifstringinstringelse#1%
+\def\syst_helpers_if_instring_else_indeed#1%
{\if#1@%
\expandafter\secondoftwoarguments
\else
@@ -4547,9 +4619,9 @@
\fi}
\def\doifstringinstringelse#1#2%
- {\expandafter\def\expandafter\p!doifstringinstringelse\expandafter##\expandafter1#1##2##3\war
- {\pp!doifstringinstringelse##2}%
- \expandafter\expandafter\expandafter\p!doifstringinstringelse\expandafter#2#1@@\war}
+ {\expandafter\def\expandafter\syst_helpers_if_instring_else\expandafter##\expandafter1#1##2##3\_e_o_s_
+ {\syst_helpers_if_instring_else_indeed##2}%
+ \expandafter\expandafter\expandafter\syst_helpers_if_instring_else\expandafter#2#1@@\_e_o_s_}
%D \macros
%D {appendtoks,prependtoks,appendtoksonce,prependtoksonce,
@@ -4569,36 +4641,39 @@
%D These macros are clones of the ones implemented in page~378 of
%D Knuth's \TeX book.
-\newtoks\@@scratchtoks
+\newtoks\t_syst_helpers_scratch
+\let \m_syst_helpers_scratch\empty
+
+% no longer \def but \let to target toks
-\unexpanded\def\appendtoks {\doappendtoks \relax}
-\unexpanded\def\prependtoks {\doprependtoks \relax}
-\unexpanded\def\appendtoksonce {\doappendtoksonce \relax}
-\unexpanded\def\prependtoksonce{\doprependtoksonce\relax}
+\unexpanded\def\appendtoks {\syst_helpers_append_toks \relax}
+\unexpanded\def\prependtoks {\syst_helpers_prepend_toks \relax}
+\unexpanded\def\appendtoksonce {\syst_helpers_append_toks_once \relax}
+\unexpanded\def\prependtoksonce{\syst_helpers_prepend_toks_once\relax}
-\def\dodoappendtoks
- {\dodoglobal\@@toks\doubleexpandafter{\expandafter\the\expandafter\@@toks\the\@@scratchtoks}}
+\def\syst_helpers_append_toks_indeed
+ {\dodoglobal\m_syst_helpers_scratch\doubleexpandafter{\expandafter\the\expandafter\m_syst_helpers_scratch\the\t_syst_helpers_scratch}}
-\def\dodoprependtoks
- {\dodoglobal\@@toks\doubleexpandafter{\expandafter\the\expandafter\@@scratchtoks\the\@@toks}}
+\def\syst_helpers_prepend_toks_indeed
+ {\dodoglobal\m_syst_helpers_scratch\doubleexpandafter{\expandafter\the\expandafter\t_syst_helpers_scratch\the\m_syst_helpers_scratch}}
-\def\doappendtoks#1\to#2%
- {\def\@@toks{#2}%
- \@@scratchtoks\expandafter{\gobbleoneargument#1}\dodoappendtoks}
+\def\syst_helpers_append_toks#1\to#2%
+ {\let\m_syst_helpers_scratch#2%
+ \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}\syst_helpers_append_toks_indeed}
-\def\doprependtoks#1\to#2%
- {\def\@@toks{#2}%
- \@@scratchtoks\expandafter{\gobbleoneargument#1}\dodoprependtoks}
+\def\syst_helpers_prepend_toks#1\to#2%
+ {\let\m_syst_helpers_scratch#2%
+ \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}\syst_helpers_prepend_toks_indeed}
-\def\doappendtoksonce#1\to#2%
- {\def\@@toks{#2}%
- \@@scratchtoks\expandafter{\gobbleoneargument#1}%
- \doifintokselse\@@scratchtoks\@@toks\donothing\dodoappendtoks}
+\def\syst_helpers_append_toks_once#1\to#2%
+ {\let\m_syst_helpers_scratch#2%
+ \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+ \doifintokselse\t_syst_helpers_scratch\m_syst_helpers_scratch\donothing\syst_helpers_append_toks_indeed}
-\def\doprependtoksonce#1\to#2%
- {\def\@@toks{#2}%
- \@@scratchtoks\expandafter{\gobbleoneargument#1}%
- \doifintokselse\@@scratchtoks\@@toks\donothing\dodoprependtoks}
+\def\syst_helpers_prepend_toks_once#1\to#2%
+ {\let\m_syst_helpers_scratch#2%
+ \t_syst_helpers_scratch\expandafter{\gobbleoneargument#1}%
+ \doifintokselse\t_syst_helpers_scratch\m_syst_helpers_scratch\donothing\syst_helpers_prepend_toks_indeed}
%D The test macro:
@@ -4616,70 +4691,27 @@
% {\scratchtoks{a\relax b} \removetoks \relax\from\scratchtoks [\showthe\scratchtoks]}
\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}%
- \expandafter\doremovetoks\the#2\empty\empty\empty#1\empty\empty\empty\\}
+ {\def\syst_helpers_remove_toks##1#1##2\empty\empty\empty##3\_e_o_t_
+ {\def\m_syst_string_one{##3}%
+ \ifx\m_syst_string_one\empty#2{##1}\else#2{##1##2}\fi}%
+ \expandafter\syst_helpers_remove_toks\the#2\empty\empty\empty#1\empty\empty\empty\_e_o_t_}
%D Also:
-\unexpanded\def\appendetoks #1\to{\normalexpanded{\noexpand\appendtoks #1}\to}
-\unexpanded\def\prependetoks#1\to{\normalexpanded{\noexpand\prependtoks#1}\to}
+\unexpanded\def\appendetoks #1\to{\normalexpanded{\appendtoks #1}\to}
+\unexpanded\def\prependetoks#1\to{\normalexpanded{\prependtoks#1}\to}
%D Hm.
-\def\flushtoks#1% nb: can reassing to #1 again, hence the indirectness
- {\@@scratchtoks#1\relax
+\unexpanded\def\flushtoks#1% nb: can reassing to #1 again, hence the indirectness
+ {\t_syst_helpers_scratch#1\relax
\dodoglobal#1\emptytoks
- \the\@@scratchtoks\relax}
+ \the\t_syst_helpers_scratch\relax}
% better: \def\flushtoks#1{\normalexpanded{\noexpand\dodoglobal#1\emptytoks\the#\relax}}
\let\dotoks\the
-% 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}
%D
@@ -4697,33 +4729,35 @@
%D Both implementations show some insight in the manipulation
%D of arguments.
-\def\beforesplitstring#1\at#2\to#3%
- {\def\dosplitstring##1#2##2#2##3\\%
+\let\syst_helpers_split_string\relax
+
+\unexpanded\def\beforesplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2#2##3\\%
{\def#3{##1}}%
- \expandafter\dosplitstring#1#2#2\\}
+ \expandafter\syst_helpers_split_string#1#2#2\\}
-\def\aftersplitstring#1\at#2\to#3%
- {\def\dosplitstring##1#2##2@@@##3\\%
+\unexpanded\def\aftersplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2@@@##3\\%
{\def#3{##2}}%
- \expandafter\dosplitstring#1@@@#2@@@\\}
+ \expandafter\syst_helpers_split_string#1@@@#2@@@\\}
%D \macros
%D {splitstring,greedysplitstring}
%D
%D A bonus macro.
-\def\splitstring#1\at#2\to#3\and#4%
- {\def\dosplitstring##1#2##2\empty\empty\empty##3\\%
+\unexpanded\def\splitstring#1\at#2\to#3\and#4%
+ {\def\syst_helpers_split_string##1#2##2\empty\empty\empty##3\\%
{\def#3{##1}%
- \def\dosplitstring{##3}%
- \ifx\dosplitstring\empty
+ \def\syst_helpers_split_string{##3}%
+ \ifx\syst_helpers_split_string\empty
\let#4\empty
\else
\def#4{##2}%
\fi}%
- \expandafter\dosplitstring#1\empty\empty\empty#2\empty\empty\empty\\}
+ \expandafter\syst_helpers_split_string#1\empty\empty\empty#2\empty\empty\empty\\}
-\def\greedysplitstring#1\at#2\to#3\and#4%
+\unexpanded\def\greedysplitstring#1\at#2\to#3\and#4%
{\edef\asciib{#1}%
\let\asciic\asciib
\let#3\empty
@@ -4745,20 +4779,20 @@
%D aftertestandsplitstring,
%D testandsplitstring}
-\def\beforetestandsplitstring#1\at#2\to#3%
- {\def\dosplitstring##1#2##2#2##3##4\\%
+\unexpanded\def\beforetestandsplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string##1#2##2#2##3##4\\%
{\ifx##3\empty\let#3\empty\else\def#3{##1}\fi}%
- \expandafter\dosplitstring#1#2#2\empty\\}
+ \expandafter\syst_helpers_split_string#1#2#2\empty\\}
-\def\aftertestandsplitstring#1\at#2\to#3%
- {\def\dosplitstring ##1#2##2@@@##3##4\\%
+\unexpanded\def\aftertestandsplitstring#1\at#2\to#3%
+ {\def\syst_helpers_split_string ##1#2##2@@@##3##4\\%
{\ifx##3\empty\let#3\empty\else\def#3{##2}\fi}%
- \expandafter\dosplitstring #1@@@#2@@@\empty\\}
+ \expandafter\syst_helpers_split_string #1@@@#2@@@\empty\\}
\def\testandsplitstring#1\at#2\to#3\and#4%
- {\def\dosplitstring##1#2##2#2##3##4\\%
+ {\def\syst_helpers_split_string##1#2##2#2##3##4\\%
{\ifx##3\empty\let#3\empty\let#4\empty\else\def#3{##1}\def#4{##2}\fi}%
- \expandafter\dosplitstring#1#2#2\empty\\}
+ \expandafter\syst_helpers_split_string#1#2#2\empty\\}
%D \macros
%D {removesubstring}
@@ -4771,9 +4805,9 @@
%D
%D Which in terms of \TEX\ looks like:
-\def\removesubstring#1\from#2\to#3%
- {\splitstring#2\to\!!stringa\and\!!stringb
- \dodoglobal#3{\!!stringa\!!stringb}}
+\unexpanded\def\removesubstring#1\from#2\to#3%
+ {\splitstring#2\to\m_syst_string_one\and\m_syst_string_two
+ \dodoglobal#3{\m_syst_string_one\m_syst_string_two}}
%D \macros
%D {appendtocommalist,prependtocommalist,
@@ -4848,9 +4882,9 @@
{\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}
\unexpanded\def\robustdoifinsetelse#1#2%
- {\edef\!!stringa{\detokenize\expandafter{\normalexpanded{#1}}}%
- \edef\!!stringb{\detokenize\expandafter{\normalexpanded{#2}}}%
- \rawdoifinsetelse\!!stringa\!!stringb}
+ {\edef\m_syst_string_one{\detokenize\expandafter{\normalexpanded{#1}}}%
+ \edef\m_syst_string_two{\detokenize\expandafter{\normalexpanded{#2}}}%
+ \rawdoifinsetelse\m_syst_string_one\m_syst_string_two}
\unexpanded\def\robustaddtocommalist#1#2% {item} \cs
{\robustdoifinsetelse{#1}#2\resetglobal
@@ -4860,11 +4894,11 @@
{\robustdoifinsetelse{#1}#2\resetglobal
{\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}
-\def\xsplitstring#1#2% \cs {str}
- {\def\dosplitstring##1,#2,##2,#2,##3\\%
- {\edef\!!stringa{\bcleanedupcommalist##1\empty\empty\relax}%
- \edef\!!stringb{\acleanedupcommalist##2,,\relax}}%
- \expandafter\dosplitstring\expandafter,#1,,#2,,#2,\\}
+\unexpanded\def\xsplitstring#1#2% \cs {str}
+ {\def\syst_helpers_split_string##1,#2,##2,#2,##3\\%
+ {\edef\m_syst_string_one{\bcleanedupcommalist##1\empty\empty\relax}%
+ \edef\m_syst_string_two{\acleanedupcommalist##2,,\relax}}%
+ \expandafter\syst_helpers_split_string\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}
@@ -4872,12 +4906,12 @@
\unexpanded\def\removefromcommalist#1#2% to be sped up
{\rawdoifinsetelse{#1}#2%
- {\normalexpanded{\noexpand\xsplitstring\noexpand#2{#1}}%
+ {\normalexpanded{\xsplitstring\noexpand#2{#1}}%
\dodoglobal\edef#2%
- {\ifx\!!stringa\empty
- \!!stringb
+ {\ifx\m_syst_string_one\empty
+ \m_syst_string_two
\else
- \!!stringa\ifx\!!stringb\empty\else,\!!stringb\fi
+ \m_syst_string_one\ifx\m_syst_string_two\empty\else,\m_syst_string_two\fi
\fi}}
\resetglobal}
@@ -4897,52 +4931,35 @@
%D \substituteincommalist{old}{new}{list}
%D \stoptyping
-\def\substituteincommalist#1#2#3% old, new, list (slooow)
- {\edef\!!stringb{#1}%
- \edef\!!stringd{#2}%
- \let\!!stringa#3%
- \let#3\empty
- \def\dosubstituteincommalist##1%
- {\edef\!!stringc{##1}%
- \ifx\!!stringb\!!stringc
- \ifx\!!stringd\empty\else
- \edef#3{#3\ifx#3\empty\else,\fi\!!stringd}%
- \fi
- \def\docommand####1{\edef#3{#3,####1}}%
- \else
- \edef#3{#3\ifx#3\empty\else,\fi##1}%
- \fi}%
- \expandafter\rawprocesscommacommand\expandafter[\!!stringa]\dosubstituteincommalist}
-
-%D A not so useful macro:
-
-\def\dodofrontstrip[#1#2]#3%
- {\ifx#1\space
- \def#3{#2}%
+\def\syst_helpers_substitute_in_comma_list_step#1%
+ {\edef\m_syst_string_three{#1}%
+ \ifx\m_syst_string_one\m_syst_string_three
+ \ifx\m_syst_string_two\empty \else
+ \edef\m_syst_string_four{\ifx\m_syst_string_four\empty\else\m_syst_string_four,\fi\m_syst_string_two}%
+ \fi
\else
- \def#3{#1#2}%
+ \edef\m_syst_string_four{\ifx\m_syst_string_four\empty\else\m_syst_string_four,\fi#1}%
\fi}
-\def\dofrontstrip#1%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty \else
- \expandafter\dodofrontstrip\expandafter[#1]#1%
- \fi}
+\unexpanded\def\substituteincommalist#1#2#3% old, new, list (slooow)
+ {\edef\m_syst_string_one{#1}%
+ \edef\m_syst_string_two{#2}%
+ \let\m_syst_string_four\empty
+ \normalexpanded{\rawprocesscommacommand[#3]}\syst_helpers_substitute_in_comma_list_step
+ \let#3\m_syst_string_four}
%D \macros
%D {replaceincommalist}
%D
-%D The next macro can be used to replace an indexed element
-%D in a commalist:
+%D The next macro can be used to replace an indexed element in a commalist:
%D
%D \starttyping
%D \replaceincommalist\MyList{2}
%D \stoptyping
%D
-%D Element~2 will be replaced by the current meaning of the macro
-%D \type {\newcommalistelement}. The old meaning is saved in
-%D \type {\commalistelement}. The replacement honors grouped items,
-%D like in:
+%D Element~2 will be replaced by the current meaning of the macro \type
+%D {\newcommalistelement}. The old meaning is saved in \type {\commalistelement}.
+%D The replacement honors grouped items, like in:
%D
%D \starttyping
%D \def\MyList{a,b,c,d,e,f} \replaceincommalist\MyList{3}
@@ -4950,43 +4967,50 @@
%D \def\MyList{a,{b,c},d,e,f} \replaceincommalist\MyList{3}
%D \def\MyList{a,b,c,{d,e,f}} \replaceincommalist\MyList{3}
%D \stoptyping
+%D
+%D This macro was used in the bibtex code (and is probably no longer needed).
+
+\newcount\c_syst_helpers_comma_list_index
+\let \m_syst_helpers_comma_list_target\empty
\let\newcommalistelement\empty
-\def\replaceincommalist#1#2% #1 = commalistelement #2 = position starts at 1
- {\def\doreplaceincommalist##1%
- {\ifnum\commalistcounter=#2\relax
- \ifx\newcommalistelement\empty\else
- \ifx\newcommalist\empty
- \let\newcommalist\newcommalistelement
- \else
- \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter
- \newcommalist\expandafter\expandafter\expandafter
- {\expandafter\newcommalist\expandafter,\newcommalistelement}%
- \fi
- \fi
- \def\commalistelement{##1}%
- \else
- \ifx\newcommalist\empty
- \ifx\nexttoken\bgroup % is known -)
- \def\newcommalist{{##1}}%
- \else
- \def\newcommalist{##1}%
- \fi
- \else
- \ifx\nexttoken\bgroup % is known -)
- \expandafter\def\expandafter\newcommalist\expandafter{\newcommalist,{##1}}%
- \else
- \expandafter\def\expandafter\newcommalist\expandafter{\newcommalist,##1}%
- \fi
- \fi
- \fi
- \advance\commalistcounter\plusone}%
+\def\syst_helpers_replace_in_comma_list_step#1%
+ {\ifnum\commalistcounter=\c_syst_helpers_comma_list_index\relax
+ \ifx\newcommalistelement\empty\else
+ \ifx\m_syst_helpers_comma_list_target\empty
+ \let\m_syst_helpers_comma_list_target\newcommalistelement
+ \else
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter
+ \m_syst_helpers_comma_list_target\expandafter\expandafter\expandafter
+ {\expandafter\m_syst_helpers_comma_list_target\expandafter,\newcommalistelement}%
+ \fi
+ \fi
+ \def\commalistelement{#1}%
+ \else
+ \ifx\m_syst_helpers_comma_list_target\empty
+ \ifx\nexttoken\bgroup % is known -)
+ \def\m_syst_helpers_comma_list_target{{#1}}%
+ \else
+ \def\m_syst_helpers_comma_list_target{#1}%
+ \fi
+ \else
+ \ifx\nexttoken\bgroup % is known -)
+ \expandafter\def\expandafter\m_syst_helpers_comma_list_target\expandafter{\m_syst_helpers_comma_list_target,{#1}}%
+ \else
+ \expandafter\def\expandafter\m_syst_helpers_comma_list_target\expandafter{\m_syst_helpers_comma_list_target,#1}%
+ \fi
+ \fi
+ \fi
+ \advance\commalistcounter\plusone}
+
+\unexpanded\def\replaceincommalist#1#2% #1 = commalistelement #2 = position starts at 1
+ {\c_syst_helpers_comma_list_index#2\relax
+ \let\m_syst_helpers_comma_list_target\empty
\let\commalistelement\empty
- \let\newcommalist\empty
\commalistcounter\plusone
- \expandafter\processcommalist\expandafter[#1]\doreplaceincommalist
- \dodoglobal\let#1\newcommalist}
+ \expandafter\processcommalist\expandafter[#1]\syst_helpers_replace_in_comma_list_step
+ \dodoglobal\let#1\m_syst_helpers_comma_list_target}
%D \macros
%D {globalprocesscommalist}
@@ -4997,15 +5021,17 @@
%D handling comma lists in alignments. In these situations the
%D next macro can be of use.
-\def\globalprocesscommaitem#1,%
+\let\m_syst_helpers_comma_list_command_global\empty
+
+\def\syst_helpers_comma_list_command_global_step#1,%
{\if]#1\else
- \globalcommacommand{#1}%
- \expandafter\globalprocesscommaitem
+ \m_syst_helpers_comma_list_command_global{#1}%
+ \expandafter\syst_helpers_comma_list_command_global_step
\fi}
-\def\globalprocesscommalist[#1]#2%
- {\global\let\globalcommacommand#2%
- \expandafter\globalprocesscommaitem#1,],}
+\unexpanded\def\globalprocesscommalist[#1]#2%
+ {\global\let\m_syst_helpers_comma_list_command_global#2%
+ \expandafter\syst_helpers_comma_list_command_global_step#1,],}
%D \macros
%D {withoutpt,PtToCm,
@@ -5082,36 +5108,36 @@
%D
%D Beware: global!
-\def\@sl@{@sl@}
-\def\@sg@{@sg@}
+\installsystemnamespace{localpushedmacro}
+\installsystemnamespace{globalpushedmacro}
-\let\@@pushedmacro\empty
+\let\m_syst_helpers_push_macro\empty
-\def\globalpushmacro#1%
- {\xdef\@@pushedmacro{\string#1}%
- \ifcsname\@sg@\@@pushedmacro\endcsname \else
- \expandafter\newcount\csname\@sg@\@@pushedmacro\endcsname
+\unexpanded\def\globalpushmacro#1%
+ {\xdef\m_syst_helpers_push_macro{\string#1}%
+ \ifcsname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \else
+ \expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
\fi
- \global\advance\csname\@sg@\@@pushedmacro\endcsname \plusone
- \global\expandafter\let\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}
-
-\def\globalpopmacro#1%
- {\xdef\@@pushedmacro{\string#1}%
- \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
- \expandafter\newcount\csname\@sl@\@@pushedmacro\endcsname
+ \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \plusone
+ \global\expandafter\let\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1}
+
+\unexpanded\def\globalpopmacro#1%
+ {\xdef\m_syst_helpers_push_macro{\string#1}%
+ \global\expandafter\let\expandafter#1\csname\the\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname
+ \global\advance\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname \minusone}
+
+\unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup
+ {\xdef\m_syst_helpers_push_macro{\string#1}%
+ \ifcsname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \else
+ \expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
\fi
- \global\advance\csname\@sl@\@@pushedmacro\endcsname \plusone
- \global\expandafter\let\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}
+ \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \plusone
+ \global\expandafter\let\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1}
-\def\localpopmacro#1%
- {\xdef\@@pushedmacro{\string#1}%
- \expandafter\let\expandafter#1\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
- \global\advance\csname\@sl@\@@pushedmacro\endcsname \minusone }
+\unexpanded\def\localpopmacro#1%
+ {\xdef\m_syst_helpers_push_macro{\string#1}%
+ \expandafter\let\expandafter#1\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname
+ \global\advance\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname \minusone }
\let\pushmacro\localpushmacro
\let\popmacro \localpopmacro
@@ -5133,49 +5159,28 @@
%D These examples show us that an optional can be used. The
%D value provided is added to \type{\localhsize}.
-% todo: a fast non argument variant
-
\newdimen\localhsize
-% \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}
+ {\localhsize\availablehsize}
\def\syst_helpers_set_local_hsize_yes[#1]%
{\syst_helpers_set_local_hsize_nop
\advance\localhsize#1\relax}
+\def\availablehsize
+ {\dimexpr
+ \hsize-\leftskip-\rightskip
+ \ifnum\hangafter<\zerocount
+ \ifdim\hangindent>\zeropoint-\else+\fi\hangindent
+ \fi
+ \relax}
+
%D \macros
%D {doifvalue,doifnotvalue,doifelsevalue,
%D doifnothing,doifsomething,doifelsenothing,
@@ -5187,81 +5192,84 @@
%D tokens per call. Anyone familiar with the not||values
%D ones, can derive their meaning from the definitions.
-\def\doifvalue#1#2%
- {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
- \ifx\!!stringa\!!stringb
+\unexpanded\def\doifvalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-\def\doifnotvalue#1#2%
- {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
- \ifx\!!stringa\!!stringb
+\unexpanded\def\doifnotvalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
-\def\doifelsevalue#1#2%
- {\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
- \ifx\!!stringa\!!stringb
+\unexpanded\def\doifelsevalue#1#2%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\def\doifnothing#1%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+\unexpanded\def\doifnothing#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-\def\doifsomething#1%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+\unexpanded\def\doifsomething#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
-\def\doifelsenothing#1%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+\unexpanded\def\doifelsenothing#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\def\doifsomethingelse#1%
- {\edef\!!stringa{#1}%
- \ifx\!!stringa\empty
+\unexpanded\def\doifsomethingelse#1%
+ {\edef\m_syst_string_one{#1}%
+ \ifx\m_syst_string_one\empty
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
\fi}
-\def\doifvaluenothing#1%
- {\edef\!!stringa{\csname#1\endcsname}%
- \ifx\!!stringa\empty
+\unexpanded\def\doifvaluenothing#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-\def\doifvaluesomething#1%
- {\edef\!!stringa{\csname#1\endcsname}%
- \ifx\!!stringa\empty
+\unexpanded\def\doifvaluesomething#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
-\def\doifelsevaluenothing#1%
- {\edef\!!stringa{\csname#1\endcsname}%
- \ifx\!!stringa\empty
+\unexpanded\def\doifelsevaluenothing#1%
+ {\edef\m_syst_string_one{\csname#1\endcsname}%
+ \ifx\m_syst_string_one\empty
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
@@ -5308,9 +5316,9 @@
\processcommalist[#3]\syst_helpers_do_common_check_all
\ifdone\expandafter#1\else\expandafter#2\fi}
-\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 }
+\unexpanded\def\doifallcommonelse{\syst_helpers_do_if_all_common_else\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifallcommon {\syst_helpers_do_if_all_common_else\firstofonearguments\gobbleoneargument }
+\unexpanded\def\doifnotallcommon {\syst_helpers_do_if_all_common_else\gobbleoneargument \firstofonearguments }
%D \macros
%D {DOIF,DOIFELSE,DOIFNOT}
@@ -5328,39 +5336,42 @@
%D
%D We have to use a two||step implementation, because the
%D expansion has to take place outside \type{\uppercase}.
+%D
+%D These might up as \LUA based helpers (i.e. considere these
+%D obsolete:
\unexpanded\def\syst_helpers_do_IF#1#2%
- {\uppercase{{$#1$}{$#2$}}%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
\unexpanded\def\syst_helpers_do_IF_NOT#1#2%
- {\uppercase{{$#1$}{$#2$}}%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
\unexpanded\def\syst_helpers_do_IF_ELSE#1#2%
- {\uppercase{{$#1$}{$#2$}}%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
\unexpanded\def\syst_helpers_do_IF_INSTRING_ELSE#1#2%
- {\uppercase{{$#1$}{$#2$}}%
+ {\uppercase{\syst_helpers_do_if_in_string_else{$#1$}{$#2$}}%
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\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}}}
+\unexpanded\def\DOIF #1#2{\normalexpanded{\syst_helpers_do_IF {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFNOT #1#2{\normalexpanded{\syst_helpers_do_IF_NOT {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFELSE #1#2{\normalexpanded{\syst_helpers_do_IF_ELSE {#1}{#2}}}% will become obsolete
+\unexpanded\def\DOIFINSTRINGELSE #1#2{\normalexpanded{\syst_helpers_do_IF_INSTRING_ELSE{#1}{#2}}}% will become obsolete
%D \macros
%D {dosingleargumentwithset,
@@ -5396,25 +5407,25 @@
%D \starttyping
%D \definesomething[alfa,beta,...][variable=...,...]
%D \stoptyping
-%D
-%D Now a whole bunch of variables like \type{\@@xxalfavariable}
-%D and \type{\@@xxbetavariable} is defined.
-\def\dodoublewithset[#1][#2]%
+\let\m_syst_helpers_with_set_command\empty
+\let\syst_helpers_with_set_step \relax
+
+\def\syst_helpers_with_set_double[#1][#2]%
{\doifsomething{#1}
- {\def\@@dodowithsetcommand##1{\@@dowithsetcommand[##1][#2]}%
- \processcommalist[#1]\@@dodowithsetcommand}}
+ {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}%
+ \processcommalist[#1]\syst_helpers_with_set_step}}
-\def\dotriplewithset[#1][#2][#3]%
+\def\syst_helpers_with_set_triple[#1][#2][#3]%
{\doifsomething{#1}
- {\def\@@dodowithsetcommand##1{\@@dowithsetcommand[##1][#2][#3]}%
- \processcommalist[#1]\@@dodowithsetcommand}}
+ {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}%
+ \processcommalist[#1]\syst_helpers_with_set_step}}
-\def\dodoubleemptywithset #1{\let\@@dowithsetcommand#1\dodoubleempty \dodoublewithset} % \command
-\def\dodoubleargumentwithset#1{\let\@@dowithsetcommand#1\dodoubleargument\dodoublewithset} % \command
+\def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command
+\def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command
-\def\dotripleemptywithset #1{\let\@@dowithsetcommand#1\dotripleempty \dotriplewithset} % \command
-\def\dotripleargumentwithset#1{\let\@@dowithsetcommand#1\dotripleargument\dotriplewithset} % \command
+\def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command
+\def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command
%D \macros
%D {stripcharacters,stripspaces}
@@ -5441,16 +5452,18 @@
%D As we can see below, spaces following a control sequence are
%D to enclosed in \type{{}}.
-\def\stripcharacter#1\from#2\to#3%
- {\def\dostripcharacter##1#1##2\end
- {\edef\!!strippedstring{\!!strippedstring##1}%
- \doifnotempty{##2}{\dostripcharacter##2\end}}%
- \let\!!strippedstring\empty
- \edef\!!stringa{#2}%
- \expandafter\dostripcharacter\!!stringa#1\end
- \dodoglobal\let#3\!!strippedstring}
+\let\m_syst_helpers_strip_character\empty
+
+\unexpanded\def\stripcharacter#1\from#2\to#3%
+ {\def\syst_helpers_strip_character##1#1##2\end
+ {\edef\m_syst_helpers_strip_character{\m_syst_helpers_strip_character##1}%
+ \doifnotempty{##2}{\syst_helpers_strip_character##2\end}}%
+ \let\m_syst_helpers_strip_character\empty
+ \edef\m_syst_string_one{#2}%
+ \expandafter\syst_helpers_strip_character\m_syst_string_one#1\end
+ \dodoglobal\let#3\m_syst_helpers_strip_character}
-\def\stripspaces\from#1\to#2% will become \unspacestring#1\from#2
+\unexpanded\def\stripspaces\from#1\to#2% will become \unspacestring#1\from#2
{\stripcharacter{ }\from#1\to#2}
%D \macros
@@ -5459,7 +5472,7 @@
%D The next macro does the same but is more compatible with other macros,
%D like \type {\convert...}.
-\def\unspacestring#1\to#2%
+\unexpanded\def\unspacestring#1\to#2%
{\stripcharacter{ }\from#1\to#2}
%D \macros
@@ -5482,8 +5495,6 @@
%D We can of course gobble more arguments using the
%D appropriate gobbling command.
-\newif\ifexecuted % general purpose
-
\def\executeifdefined#1% #2 / never change this one again
{\ifcsname#1\endcsname
\csname#1\expandafter\expandafter\expandafter\endcsname\expandafter\gobbleoneargument
@@ -5510,65 +5521,15 @@
%D Is this one still needed?
-\def\p!doifsomespaceelse#1 #2#3\war{\if\noexpand#2@}
+\def\syst_helpers_if_some_space_else#1 #2#3\_e_o_s_{\if\noexpand#2@}
-\def\doifsomespaceelse#1% % #2#3%
- {\p!doifsomespaceelse#1 @ @\war % #3\else#2\fi}
+\def\doifsomespaceelse#1% % #2#3%
+ {\syst_helpers_if_some_space_else#1 @ @\_e_o_s_ % #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 {processseparatedlist}
%D
@@ -5600,56 +5561,61 @@
%D Therefore we smuggle a \type {\relax} in front of the
%D argument, which we remove afterwards.
-\def\doprocessseparatedlist#1]#2[#3]#4%
- {\def\dodoprocessseparatedlist##1##2#3%
- {\def\!!stringa{##2}% suggested by VZ
+\let\syst_helpers_process_separated_list_step\relax
+
+\def\syst_helpers_process_separated_list#1]#2[#3]#4%
+ {\def\syst_helpers_process_separated_list_step##1##2#3%
+ {\def\m_syst_string_one{##2}% suggested by VZ
\if]##1%
- \let\dodoprocessseparatedlist\relax
- \else\ifx\blankspace\!!stringa
+ \let\syst_helpers_process_separated_list_step\relax
+ \else\ifx\blankspace\m_syst_string_one
#4{##1}%
\else\if]##2%
- \let\dodoprocessseparatedlist\relax
+ \let\syst_helpers_process_separated_list_step\relax
\else
#4{##1##2}%
\fi\fi\fi
- \dodoprocessseparatedlist}%
- \expandafter\dodoprocessseparatedlist\gobbleoneargument#1#3]#3}
+ \syst_helpers_process_separated_list_step}%
+ \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#3]#3}
-\def\processseparatedlist[%
- {\doprocessseparatedlist\relax}
+\unexpanded\def\processseparatedlist[%
+ {\syst_helpers_process_separated_list\relax}
%D \macros
%D {processlist}
%D
-%D An even more general list processing macro is the
-%D following one:
+%D An even more general list processing macro is the following one:
%D
%D \starttyping
%D \processlist{beginsym}{endsym}{separator}\docommand list
%D \stoptyping
%D
-%D This one supports arbitrary open and close symbols as well
-%D as user defined separators.
+%D This one supports arbitrary open and close symbols as well as user
+%D defined separators.
%D
%D \starttyping
%D \processlist(){=>}\docommand(a=>b=>c=>d)
%D \stoptyping
-\def\processlist#1#2#3#4% no blank skipping !
- {\def\doprocesslist##1#2%
- {\def\dodoprocesslist####1####2#3%
+\let\syst_helpers_process_any_list \relax
+\let\syst_helpers_process_any_list_indeed\relax
+\let\syst_helpers_process_any_list_step \relax
+
+\unexpanded\def\processlist#1#2#3#4% no blank skipping !
+ {\def\syst_helpers_process_any_list_indeed##1#2%
+ {\def\syst_helpers_process_any_list_step####1####2#3%
{\ifx#2####1%
- \let\dodoprocesslist\relax
+ \let\syst_helpers_process_any_list_step\relax
\else\ifx#2####2%
- \let\dodoprocesslist\relax
+ \let\syst_helpers_process_any_list_step\relax
\else
#4{####1####2}%
\fi\fi
- \dodoprocesslist}%
- \expandafter\dodoprocesslist\gobbleoneargument##1#3#2#3}%
- \def\dodoprocesslist#1%
- {\doprocesslist\relax}%
- \dodoprocesslist}
+ \syst_helpers_process_any_list_step}%
+ \expandafter\syst_helpers_process_any_list_step\gobbleoneargument##1#3#2#3}%
+ \def\syst_helpers_process_any_list#1%
+ {\syst_helpers_process_any_list_indeed\relax}%
+ \syst_helpers_process_any_list}
%D \macros
%D {processassignlist}
@@ -5665,12 +5631,12 @@
%D This command can be integrated in \type{\getparameters}, but
%D we decided best not to do so.
-\def\processassignlist#1[#2]#3%
- {\def\p!dodogetparameter[##1=##2=##3]%
+\unexpanded\def\processassignlist#1[#2]#3%
+ {\def\syst_helpers_process_assign_list_assign[##1=##2=##3]%
{\doifnot{##3}\relax{#3{##1}}}%
- \def\p!dogetparameter##1%
- {\p!dodogetparameter[##1==\relax]}%
- \processcommalist[#2]\p!dogetparameter}
+ \def\syst_helpers_process_assign_list_step##1%
+ {\syst_helpers_process_assign_list_assign[##1==\relax]}%
+ \processcommalist[#2]\syst_helpers_process_assign_list_step}
%D \macros
%D {untextargument
@@ -5687,20 +5653,22 @@
%D They remove braces and backslashes and give us something to
%D sort.
-\def\untexsomething
+\let\m_syst_helpers_untexed\empty
+
+\unexpanded\def\untexsomething
{\begingroup
\catcode\leftbraceasciicode \ignorecatcode
\catcode\rightbraceasciicode\ignorecatcode
\escapechar\minusone
- \dountexsomething}
+ \syst_helpers_untex_something}
-\def\dountexsomething#1#2\to#3%
- {\doglobal#1#2\to\untexedargument
+\def\syst_helpers_untex_something#1#2\to#3%
+ {\doglobal#1#2\to\m_syst_helpers_untexed
\endgroup
- \let#3\untexedargument}
+ \let#3\m_syst_helpers_untexed}
-\def\untexargument{\untexsomething\convertargument}
-\def\untexcommand {\untexsomething\convertcommand}
+\unexpanded\def\untexargument{\untexsomething\convertargument}
+\unexpanded\def\untexcommand {\untexsomething\convertcommand}
%D \macros
%D {ScaledPointsToBigPoints,ScaledPointsToWholeBigPoints}
@@ -5725,14 +5693,14 @@
% \PointsToWholeBigPoints{10.53941pt}\test \test
% \PointsToWholeBigPoints{10.53942pt}\test \test
-\def\PointsToBigPoints#1#2%
+\unexpanded\def\PointsToBigPoints#1#2%
{\edef#2{\withoutpt\the\dimexpr.996264\dimexpr#1\relax\relax}}
-\def\PointsToWholeBigPoints#1#2%
+\unexpanded\def\PointsToWholeBigPoints#1#2%
{\edef#2{\the\numexpr\dimexpr.996264\dimexpr#1\relax\relax/\maxcard\relax}}
-\def\ScaledPointsToBigPoints #1{\PointsToBigPoints {\number#1\scaledpoint}}
-\def\ScaledPointsToWholeBigPoints#1{\PointsToWholeBigPoints{\number#1\scaledpoint}}
+\unexpanded\def\ScaledPointsToBigPoints #1{\PointsToBigPoints {\number#1\scaledpoint}}
+\unexpanded\def\ScaledPointsToWholeBigPoints#1{\PointsToWholeBigPoints{\number#1\scaledpoint}}
%D \macros
%D {PointsToReal}
@@ -5744,9 +5712,8 @@
%D \PointsToReal {dimension} \target
%D \stoptyping
-\def\PointsToReal#1#2%
- {\scratchdimen#1%
- \edef#2{\withoutpt\the\scratchdimen}}
+\unexpanded\def\PointsToReal#1#2%
+ {\edef#2{\withoutpt\the\dimexpr#1}}
%D \macros
%D {dontleavehmode}
@@ -5777,16 +5744,17 @@
%D
%D And finaly we got the following alternative, one that avoids
%D interfering grouping at the cost of a box.
-
-\newbox\@@dlhbox
-
-\unexpanded\def\dontleavehmode
- {\ifhmode\else \ifmmode\else
- \setbox\@@dlhbox\hbox{\mathsurround\zeropoint\everymath\emptytoks$ $}\unhbox\@@dlhbox
- \fi \fi}
-
-%D But, if you run a recent version of \TEX, we can use the new
-%D primitive:
+%D
+%D \starttyping
+%D \newbox\b_syst_helpers_dlh
+%D
+%D \unexpanded\def\dontleavehmode
+%D {\ifhmode\else \ifmmode\else
+%D \setbox\b_syst_helpers_dlh\hbox{\mathsurround\zeropoint\everymath\emptytoks$ $}\unhbox\b_syst_helpers_dlh
+%D \fi \fi}
+%D \stoptyping
+%D
+%D But, as we run a recent version of \TEX, we can use the new primitive:
\ifdefined\normalquitvmode \let\dontleavehmode\normalquitvmode \fi
@@ -5800,14 +5768,17 @@
%D \lowercasestring somestring\to\somestring
%D \stoptyping
%D
-%D the first argument may be a \type{\macro}.
+%D The first argument may be a \type{\macro}.
-\def\uppercasestring#1\to#2%
+\unexpanded\def\uppercasestring#1\to#2%
{\uppercase\expandafter{\expandafter\dodoglobal\expandafter\edef\expandafter#2\expandafter{\normalexpanded{#1}}}}
-\def\lowercasestring#1\to#2%
+\unexpanded\def\lowercasestring#1\to#2%
{\lowercase\expandafter{\expandafter\dodoglobal\expandafter\edef\expandafter#2\expandafter{\normalexpanded{#1}}}}
+%D These macros are sort of obsolete as we never use uppercase this
+%D way.
+
%D \macros
%D {handletokens}
%D
@@ -5843,25 +5814,26 @@
%D takes a real counter. The macro can be preceded by \type
%D {\doglobal}.
-\def\counttoken#1\in#2\to#3%
+\def\syst_helpers_count_token#1% obeys {}
+ {\def\m_syst_string_three{#1}%
+ \ifx\m_syst_string_two\m_syst_string_three \else
+ \ifx\m_syst_string_one\m_syst_string_three
+ \advance\scratchcounter\plusone
+ \fi
+ \expandafter\syst_helpers_count_token
+ \fi}
+
+\unexpanded\def\counttoken#1\in#2\to#3%
{\scratchcounter\zerocount
- \def\!!stringa{#1}%
- \def\!!stringb{\end}%
- \def\docounttoken##1% obeys {}
- {\def\!!stringc{##1}%
- \ifx\!!stringb\!!stringc \else
- \ifx\!!stringa\!!stringc
- \advance\scratchcounter\plusone
- \fi
- \expandafter\docounttoken
- \fi}%
- \docounttoken#2\end
+ \def\m_syst_string_one{#1}%
+ \def\m_syst_string_two{\end}%
+ \syst_helpers_count_token#2\end
\dodoglobal#3\scratchcounter}
-\def\counttokens#1\to#2%
+\unexpanded\def\counttokens#1\to#2%
{\scratchcounter\zerocount
- \def\docounttoken##1{\advance\scratchcounter\plusone}%
- \handletokens#1\with\docounttoken
+ \def\syst_helpers_count_token##1{\advance\scratchcounter\plusone}%
+ \handletokens#1\with\syst_helpers_count_token
\dodoglobal#2\scratchcounter}
%D \macros
@@ -5871,17 +5843,17 @@
%D Consider for instance the macro for which I originally
%D wrote this token handler.
-\def\splitofftokens#1\from#2\to#3% slow but hardly used
+\unexpanded\def\splitofftokens#1\from#2\to#3% slow but hardly used
{\ifnum#1>\zerocount
\scratchcounter#1\relax
- \def\dosplitofftokens##1%
+ \def\syst_helpers_split_off_tokens##1%
{\ifnum\scratchcounter>\zerocount
\advance\scratchcounter \minusone
\edef#3{#3##1}%
\fi}%
% \let#3\empty % #3 can be #2, so:
\expandafter\let\expandafter#3\expandafter\empty
- \expandafter\handletokens#2\with\dosplitofftokens
+ \expandafter\handletokens#2\with\syst_helpers_split_off_tokens
\else
\edef#3{#2}%
\fi}
@@ -5918,27 +5890,27 @@
%D way we can handle the sentinal, a blank space and grouped
%D tokens.
-\def\dohandletokens % \nexthandledtoken is part of interface
- {\futurelet\nexthandledtoken\dodohandletokens}
+\unexpanded\def\syst_helpers_handle_tokens % \nexthandledtoken is part of interface
+ {\futurelet\nexthandledtoken\syst_helpers_handle_tokens_indeed}
\def\handletokens#1\with#2%
- {\gdef\dododohandletokens{#2}% permits more complex #2's
- \dohandletokens#1\end}
+ {\gdef\syst_helpers_handle_tokens_command{#2}% permits more complex #2's
+ \syst_helpers_handle_tokens#1\end}
-\def\dodohandletokens
+\def\syst_helpers_handle_tokens_indeed
{\ifx\nexthandledtoken\blankspace
- \expandafter\dodohandletokensone
+ \expandafter\syst_helpers_handle_tokens_indeed_one
\else\ifx\nexthandledtoken\end
\expandafter\expandafter\expandafter\gobbletwoarguments % also gobble the \end
\else
- \expandafter\expandafter\expandafter\dodohandletokenstwo
+ \expandafter\expandafter\expandafter\syst_helpers_handle_tokens_indeed_two
\fi\fi *}
-\def\dodohandletokensone * %
- {\dododohandletokens{ }\dohandletokens}
+\def\syst_helpers_handle_tokens_indeed_one * %
+ {\syst_helpers_handle_tokens_command{ }\syst_helpers_handle_tokens}
-\def\dodohandletokenstwo *#1%
- {\dododohandletokens{#1}\dohandletokens}
+\def\syst_helpers_handle_tokens_indeed_two *#1%
+ {\syst_helpers_handle_tokens_command{#1}\syst_helpers_handle_tokens}
%D This macro is tested on:
%D
@@ -6021,130 +5993,35 @@
%D This macro is first used in the tabulation macros.
\unexpanded\def\processcontent#1%
- {\begingroup\expandafter\doprocesscontent\csname#1\endcsname}
+ {\begingroup\expandafter\syst_helpers_process_content\csname#1\endcsname}
-\unexpanded\def\doprocesscontent#1#2#3%
- {\unexpanded\def\doprocesscontent##1#1%
+\unexpanded\def\syst_helpers_process_content#1#2#3%
+ {\unexpanded\def\syst_helpers_process_content##1#1%
{\endgroup\def#2{##1}#3}%
- \doprocesscontent}
+ \syst_helpers_process_content}
%D \macros
%D {dogobblesingleempty, dogobbledoubleempty}
%D
%D These two macros savely grab and dispose two arguments.
-\def\dogobblesingleempty{\dosingleempty\dodogobblesingleempty}
-\def\dogobbledoubleempty{\dodoubleempty\dodogobbledoubleempty}
+\def\dogobblesingleempty{\dosingleempty\syst_helpers_gobble_single_empty}
+\def\dogobbledoubleempty{\dodoubleempty\syst_helpers_gobble_double_empty}
-\def\dodogobblesingleempty [#1]{}
-\def\dodogobbledoubleempty[#1][#2]{}
+\def\syst_helpers_gobble_single_empty [#1]{}
+\def\syst_helpers_gobble_double_empty[#1][#2]{}
\let\gobblesingleempty\dogobblesingleempty % also used
\let\gobbledoubleempty\dogobbledoubleempty % also used
%D \macros
-%D {sortcommalist,sortcommacommand,
-%D donumericcompare,comparedresult}
-%D
-%D Sometimes we need to sort a commalist, so here is Taco's
-%D solution. This will in many cases be a list that is stored
-%D in a \type{\csname}, so both commalist and commacommands are
-%D supported. The sorting algorithm is very simple, so the list
-%D should not be too long or sorting will be very slow.
-%D
-%D \starttyping
-%D \sortcommalist[10,2,4,5,6,1,2,3,4,10,20]\donumericcompare
-%D
-%D \def\test{10,2,4,5,6,1,2,3,4,10,20}
-%D
-%D \sortcommacommand[\test]\donumericcompare
-%D \stoptyping
-%D
-%D In both cases, the result is available in the macro \type
-%D {\sortedcommalist}.
-%D
-%D Parameter \type{#2} is a macro that should accept two
-%D parameters, and it has to decide which one is larger, by
-%D setting the counter \type{\comparedresult} to~0 (for equal),
-%D 1~(if it's first argument is larger), or~2 (if it's second
-%D argument is larger).
-%D
-%D As said, these macro are largely written by Taco, and are
-%D (maybe therefore) also the first application of \type
-%D {\replaceincommalist}.
-
-\newcount\comparedresult
-
-\def\sortcommacommand[#1]%
- {\expandafter\sortcommalist\expandafter[#1]}
-
-\def\sortcommalist[#1]#2%
- {\getcommalistsize[#1]%
- \ifnum\commalistsize>1
- \let\sortedcommalist\empty
- \let\comparecommand#2%
- \processcommalist[#1]\dosortcommacommand
- \else
- \def\sortedcommalist{#1}%
- \fi}
-
-\def\dosortcommacommand#1%
- {\ifx\sortedcommalist\empty
- \def\sortedcommalist{#1}%
- \else
- \def\!!tempa{#1}%
- \ifx\!!tempa\empty\else
- \scratchcounter\plusone
- \expandafter\getcommalistsize\expandafter[\sortedcommalist]%
- \expandafter\processcommalist\expandafter[\sortedcommalist]\docompareitems
- \fi
- \fi}
-
-%D All those \type{\expandafter}'s are there because I do not
-%D want to use \type{\edef}.
-
-\def\docompareitems#1%
- {\doifnotempty{#1}
- {\expandafter\comparecommand\expandafter{\!!tempa}{#1}\relax
- %\ifcase\compareresult % equal
- \ifnum\comparedresult<2
- \ifnum\scratchcounter=\commalistsize
- \expandafter\expandafter\expandafter\def
- \expandafter\expandafter\expandafter\sortedcommalist
- \expandafter\expandafter\expandafter{\expandafter\sortedcommalist\expandafter,\!!tempa}%
- \fi
- %\or % new element larger
- % \ifnum\scratchcounter=\commalistsize
- % \expandafter\expandafter\expandafter\def
- % \expandafter\expandafter\expandafter\sortedcommalist
- % \expandafter\expandafter\expandafter{\expandafter\sortedcommalist\expandafter,\!!tempa}%
- % \fi
- \else % old element larger
- \expandafter\def\expandafter\newcommalistelement\expandafter{\!!tempa,#1}%
- \replaceincommalist\sortedcommalist\scratchcounter
- \expandafter\quitcommalist
- \fi}%
- \advance\scratchcounter \plusone} % bug, was \minusone
-
-%D The macro \type{\donumericcompare} considers everything
-%D that is not a number to be larger than any number.
-
-% 0: both are equal, 1: #1 is larger, 2: #2 is larger
-
-\def\thenumericcompare#1#2% no \relax es inside hee
- {\doifnumberelse{#1}
- {\doifnumberelse{#2}{\ifnum#1>#2 \plusone\else\ifnum#1<#2 \plustwo\else\zerocount\fi\fi}\plustwo}
- \plusone}
-
-\def\donumericcompare
- {\comparedresult\thenumericcompare}
-
-%D \macros
%D {@True, @False, @Not, @And}
%D
%D Some predicate logic functions, used in for instance the
%D math module.
+% These have rather ugly names ... will change:
+
\def\@True {00}
\def\@False {01}
\def\@Not #1{0\ifcase#11 \or\expandafter 1\else \expandafter 0\fi}
@@ -6167,10 +6044,10 @@
%D assignment inside a box. The \type{\empty}'s permits
%D gobbling while preventing spurious \type{\relax}'s.
-\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick
+\unexpanded\def\setdimensionwithunit#1#2#3% number unit dimension / nice trick
{\afterassignment\gobblefourarguments#1=#2#3pt\relax\empty\empty\empty\empty}
-\def\freezedimensionwithunit#1#2%
+\unexpanded\def\freezedimensionwithunit#1#2%
{\setdimensionwithunit\scratchdimen#1{#2}\edef#1{\the\scratchdimen}}
%D \macros
@@ -6179,25 +6056,25 @@
%D Not that fast I guess, but here's a way to test for token
%D registers being empty.
-\def\doifsometokselse#1%
- {\edef\!!stringa{\the#1}% one level expansion so quite ok
- \ifx\!!stringa\empty
+\unexpanded\def\doifsometokselse#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
\fi}
-\def\doifsometoks#1%
- {\edef\!!stringa{\the#1}% one level expansion so quite ok
- \ifx\!!stringa\empty
+\unexpanded\def\doifsometoks#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
-\def\doifemptytoks#1%
- {\edef\!!stringa{\the#1}% one level expansion so quite ok
- \ifx\!!stringa\empty
+\unexpanded\def\doifemptytoks#1%
+ {\edef\m_syst_string_one{\the#1}% one level expansion so quite ok
+ \ifx\m_syst_string_one\empty
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
@@ -6212,9 +6089,9 @@
\def\syst_helpers_strict_inspect_next_character% no user macro !
{\ifx\nexttoken\charactertoken
- \expandafter\!!stringa
+ \expandafter\m_syst_action_yes
\else
- \expandafter\!!stringb
+ \expandafter\m_syst_action_nop
\fi}
% better: push/pop
@@ -6267,10 +6144,14 @@
%D
%D Concatenate commalists:
-\def\serializecommalist[#1]%
+\let\syst_helpers_serialize_comma_list_step\relax
+
+\def\syst_helpers_serialize_comma_list_step#1%
+ {\edef\serializedcommalist{\serializedcommalist#1}}
+
+\unexpanded\def\serializecommalist[#1]%
{\let\serializedcommalist\empty
- \def\docommand##1{\edef\serializedcommalist{\serializedcommalist##1}}%
- \processcommacommand[#1]\docommand}
+ \processcommacommand[#1]\syst_helpers_serialize_comma_list_step}
%D \macros
%D {purenumber}
@@ -6346,7 +6227,7 @@
\def\filterfromvalue#1#2#3% value max n
{\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
+ \strippedcsname\gobbleoneargument % which we then gobble here
\else
\dofilterfromstr{#2}{#3}%
\fi
@@ -6364,13 +6245,27 @@
%D ... \measure{mywidth} ...
%D \stoptyping
-\def\??dm{@@dm} % brrr
+\installsystemnamespace{measure}
\unexpanded\def\definemeasure
- {\dodoubleargument\dodefinemeasure}
+ {\dodoubleargument\syst_helpers_define_measure}
-\def\dodefinemeasure[#1][#2]%
- {\expandafter\def\csname\??dm#1\endcsname{#2}}
+\def\syst_helpers_define_measure[#1][#2]%
+ {\expandafter\def\csname\??measure#1\endcsname{#2}}
+
+\unexpanded\def\freezemeasure
+ {\dodoubleargument\syst_helpers_freeze_measure}
+
+\def\syst_helpers_freede_measure[#1][#2]%
+ {\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}}
+
+\unexpanded\def\setmeasure #1#2{\expandafter\def \csname\??measure#1\endcsname{#2}} % quick way
+\unexpanded\def\setgmeasure#1#2{\expandafter\gdef\csname\??measure#1\endcsname{#2}} % quick way
+\unexpanded\def\setemeasure#1#2{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
+\unexpanded\def\setxmeasure#1#2{\expandafter\xdef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way
+
+\def\measure#1% maybe \dimexpr ... \relax
+ {\ifcsname\??measure#1\endcsname\csname\??measure#1\endcsname\else\zeropoint\fi}
% #2 could be omitted, but we want to support spaces
%
@@ -6378,13 +6273,21 @@
% \setmeasure {xx} {1cm}
% \setmeasure {xxx}{1cm}
-\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
+%D \macros
+%D {dividedsize}
+%D
+%D This one can be used inside a measure (used in m4all):
+%D
+%D \starttyping
+%D \definemeasure[columnwidth][\dividedsize\textwidth{1em}{3}]
+%D \stoptyping
-\def\measure#1% maybe \dimexpr ... \relax
- {\ifcsname\??dm#1\endcsname\csname\??dm#1\endcsname\else\zeropoint\fi}
+\def\dividedsize#1#2#3% size gap n
+ {\dimexpr
+ \ifnum\dimexpr#1\relax>\plusone
+ (\dimexpr#1\relax-\numexpr#3-\plusone\relax\dimexpr#2\relax)/#3\else#1%
+ \fi
+ \relax}
%D \macros
%D {doifdimensionelse}
@@ -6392,9 +6295,9 @@
%D This is a dirty one: we simply append a unit and discard it when needed.
\def\doifdimensionelse#1%
- {\afterassignment\dodoifdimensionelse\scratchdimen#1pt\relax}
+ {\afterassignment\syst_helpers_if_dimension_else\scratchdimen#1pt\relax}
-\def\dodoifdimensionelse#1%
+\def\syst_helpers_if_dimension_else#1%
{\ifx#1\relax
\expandafter\secondoftwoarguments
\else % #1=p ... t\relax
@@ -6418,53 +6321,57 @@
%D \NC 1 \NC \doifdimenstringelse {1}{yes}{no} \NC \NR
%D \stoptabulate
+\installsystemnamespace{dimenchecka}
+\installsystemnamespace{dimencheckb}
+\installsystemnamespace{dimencheckc}
+
\def\doifdimenstringelse#1{\normalexpanded{\noexpand\dodimenteststageone#1}\empty\empty]}
-\def\dodimenteststageone #1#2{\csname d!1!\ifcsname d!1!#2\endcsname#2\else x\fi\endcsname#2}
-\def\dodimenteststagetwo #1#2{\csname d!2!\ifcsname d!2!#2\endcsname#2\else x\fi\endcsname#2}
-\def\dodimenteststagethree #1]{\csname d!3!\ifcsname d!3!#1\endcsname#1\else x\fi\endcsname}
-
-\expandafter\let\csname d!1!x\endcsname\dodimenteststagethree
-\expandafter\let\csname d!2!x\endcsname\dodimenteststagethree
-\expandafter\let\csname d!3!x\endcsname\secondoftwoarguments
-
-\expandafter\let\csname d!1!.\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!1!,\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!1!1\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!2\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!3\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!4\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!5\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!6\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!7\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!8\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!9\endcsname\dodimenteststageone
-\expandafter\let\csname d!1!0\endcsname\dodimenteststageone
-
-\expandafter\let\csname d!2!1\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!2\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!3\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!4\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!5\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!6\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!7\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!8\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!9\endcsname\dodimenteststagetwo
-\expandafter\let\csname d!2!0\endcsname\dodimenteststagetwo
-
-\expandafter\let\csname d!3!pt\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!pc\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!in\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!bp\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!cm\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!mm\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!dd\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!cc\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!sp\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!ex\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!em\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!nd\endcsname\firstoftwoarguments
-\expandafter\let\csname d!3!nc\endcsname\firstoftwoarguments
+\def\dodimenteststageone #1#2{\csname \??dimenchecka\ifcsname \??dimenchecka#2\endcsname#2\else x\fi\endcsname#2}
+\def\dodimenteststagetwo #1#2{\csname \??dimencheckb\ifcsname \??dimencheckb#2\endcsname#2\else x\fi\endcsname#2}
+\def\dodimenteststagethree #1]{\csname \??dimencheckc\ifcsname \??dimencheckc#1\endcsname#1\else x\fi\endcsname}
+
+\expandafter\let\csname \??dimenchecka x\endcsname\dodimenteststagethree
+\expandafter\let\csname \??dimencheckb x\endcsname\dodimenteststagethree
+\expandafter\let\csname \??dimencheckc x\endcsname\secondoftwoarguments
+
+\expandafter\let\csname \??dimenchecka.\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimenchecka,\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimenchecka1\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka2\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka3\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka4\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka5\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka6\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka7\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka8\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka9\endcsname\dodimenteststageone
+\expandafter\let\csname \??dimenchecka0\endcsname\dodimenteststageone
+
+\expandafter\let\csname \??dimencheckb1\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb2\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb3\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb4\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb5\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb6\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb7\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb8\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb9\endcsname\dodimenteststagetwo
+\expandafter\let\csname \??dimencheckb0\endcsname\dodimenteststagetwo
+
+\expandafter\let\csname \??dimencheckc pt\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc pc\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc in\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc bp\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc cm\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc mm\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc dd\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc cc\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc sp\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc ex\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc em\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc nd\endcsname\firstoftwoarguments
+\expandafter\let\csname \??dimencheckc nc\endcsname\firstoftwoarguments
%D \macros
%D {comparedimension,comparedimensioneps}
@@ -6502,51 +6409,51 @@
% \copycsname xxx\endcsname\csname ..\endcsname
-\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname}
+\unexpanded\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname}
% \letcscsname \crap \csname ..\endcsname
% \letcsnamecs \csname ..\endcsname\crap
% \letcsnamecsname\csname ..\endcsname\csname ..\endcsname
-\def\letcscsname {\expandafter\let\expandafter}
-\def\letcsnamecs {\expandafter\let}
-\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter}
+\unexpanded\def\letcscsname {\expandafter\let\expandafter}
+\unexpanded\def\letcsnamecs {\expandafter\let}
+\unexpanded\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter}
% another one, add an item to a commalist
-\def\addvalue#1#2% cs item
+\unexpanded\def\addvalue#1#2% cs item
{\ifcsname#1\endcsname\else\expandafter\let\csname#1\endcsname\empty\fi
\normalexpanded{\noexpand\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}}
\def\unspaced#1%
- {\dounspaced#1\end}
+ {\syst_helpers_unspaced#1\end}
-\def\dounspaced#1%
+\def\syst_helpers_unspaced#1%
{\ifx#1\end
\expandafter\gobbleoneargument
\else
\ifx#1\blankspace\else#1\fi
\fi
- \dounspaced}
+ \syst_helpers_unspaced}
-\def\unspaceargument#1\to#2%
+\unexpanded\def\unspaceargument#1\to#2%
{\scratchcounter\catcode\spaceasciicode
\catcode\spaceasciicode\ignorecatcode
\scantextokens{\edef#2{#1}}%
\catcode\spaceasciicode\scratchcounter}
-\def\unspaceafter#1#2%
+\unexpanded\def\unspaceafter#1#2%
{\unspaceargument#2\to\ascii
\expandafter#1\expandafter{\ascii}}
% sometimes handy:
-\def\doifhasspaceelse#1%
- {\edef\!!stringa{#1}%
- \normalexpanded{\noexpand\dodoifhasspaceelse#1\space}\empty\relax}
+\unexpanded\def\doifhasspaceelse#1%
+ {\edef\m_syst_string_one{#1}%
+ \normalexpanded{\syst_helpers_if_has_space_else#1\space}\empty\relax}
-\def\dodoifhasspaceelse#1 #2#3\relax % \space\empty\relax
- {\ifx\!!stringa\space
+\unexpanded\def\syst_helpers_if_has_space_else#1 #2#3\relax % \space\empty\relax
+ {\ifx\m_syst_string_one\space
\expandafter\firstoftwoarguments
\else\ifx#2\empty
\doubleexpandafter\secondoftwoarguments
@@ -6556,67 +6463,35 @@
% this will replace loadfile once and alike !!! todo
-\def\@flg@{@flg@}
-
-\def\setflag #1{\expandafter\dodoglobal\expandafter\let\csname\@flg@#1\endcsname\zerocount}
-\def\resetflag#1{\expandafter\dodoglobal\expandafter\let\csname\@flg@#1\endcsname\plusone}
+\installsystemnamespace{flag}
-\let\ifflagged\ifcase
+\unexpanded\def\setflag #1{\expandafter\dodoglobal\expandafter\let\csname\??flag#1\endcsname\zerocount}
+\unexpanded\def\resetflag#1{\expandafter\dodoglobal\expandafter\let\csname\??flag#1\endcsname\plusone}
-\def\flag#1{\csname\@flg@#1\endcsname}
+\def\flag#1{\csname\??flag#1\endcsname}
\def\doifelseflagged#1%
- {\expandafter\ifx\csname\@flg@#1\endcsname\relax
+ {\expandafter\ifx\csname\??flag#1\endcsname\relax
\expandafter\secondoftwoarguments
- \else\ifcase\csname\@flg@#1\endcsname
+ \else\ifcase\csname\??flag#1\endcsname
\doubleexpandafter\firstoftwoarguments
\else
\doubleexpandafter\secondoftwoarguments
\fi\fi}
\def\doifnotflagged#1%
- {\expandafter\ifx\csname\@flg@#1\endcsname\relax
+ {\expandafter\ifx\csname\??flag#1\endcsname\relax
\expandafter\firstofoneargument
- \else\ifcase\csname\@flg@#1\endcsname
+ \else\ifcase\csname\??flag#1\endcsname
\doubleexpandafter\gobbleoneargument
\else
\doubleexpandafter\firstofoneargument
\fi\fi}
-\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey
+\unexpanded\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}
-% \arrayelement{test}{1}
-% \arraylength{test}
-%
-% \def\buildarray[#1][#2]%
-% {\scratchcounter=0
-% \def\docommand##1%
-% {\advance\scratchcounter by 1
-% \setvalue{@@aa#1\the\scratchcounter}{##1}}%
-% \processcommalist[#2]\docommand
-% \setevalue{@@aa#1}{\the\scratchcounter}}%
-%
-% \def\setarrayelement#1#2{\setvalue{@@aa#1#2}}
-% \def\arrayelement #1#2{\getvalue{@@aa#1#2}}
-% \def\arraylength #1{\getvalue{@@aa#1}}
-
-% \newsignal\junksignal
-%
-% \def\setjunksignal%
-% {\ifhmode
-% \hskip\junksignal
-% \let\removejunkspaces\doremovejunkspaces
-% \else
-% \let\removejunkspaces\relax
-% \fi}
-%
-% \def\doremovejunkspaces%
-% {\doloop{\ifdim\lastskip=\junksignal\unskip\else\exitloop\fi}}
-
-\def\dodoifnonzeropositiveelse#1#2\end % #3#4%
+\def\syst_helpers_if_non_zero_positive_else#1#2\end % #3#4%
{\ifx#1\relax
\ifcase\scratchcounter
\endgroup
@@ -6631,45 +6506,42 @@
\fi}
\def\doifnonzeropositiveelse#1%
- {\begingroup\afterassignment\dodoifnonzeropositiveelse\scratchcounter=0#1\relax\empty\end}
+ {\begingroup\afterassignment\syst_helpers_if_non_zero_positive_else\scratchcounter=0#1\relax\empty\end}
% here ?
-\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}}
+\unexpanded\def\dosetrawvalue #1#2#3{\expandafter \def\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawevalue#1#2#3{\expandafter\edef\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawgvalue#1#2#3{\expandafter\gdef\csname#1#2\endcsname{#3}}
+\unexpanded\def\dosetrawxvalue#1#2#3{\expandafter\xdef\csname#1#2\endcsname{#3}}
-\def\getrawparameters {\dogetparameters\dosetrawvalue }
-\def\getraweparameters {\dogetparameters\dosetrawevalue}
-\def\getrawgparameters {\dogetparameters\dosetrawgvalue}
-\def\getrawxparameters {\dogetparameters\dosetrawxvalue}
+\unexpanded\def\getrawparameters {\dogetparameters\dosetrawvalue }
+\unexpanded\def\getraweparameters {\dogetparameters\dosetrawevalue}
+\unexpanded\def\getrawgparameters {\dogetparameters\dosetrawgvalue}
+\unexpanded\def\getrawxparameters {\dogetparameters\dosetrawxvalue}
-\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete
-
-\def\splitskip#1%
- {\scratchskip#1\relax
- \dimen0\scratchskip
- \dimen2\gluestretch\scratchskip
- \dimen4\glueshrink\scratchskip}
+\unexpanded\def\globalgetrawparameters{\dogetparameters\dosetrawgvalue} % obsolete
-\newcount\modcounter
+%D Sort of obsolete:
-\def\dosetmodulo#1#2#3%
- {\modcounter#1\divide\modcounter#2\multiply\modcounter#2%
- #3#1\advance#3-\modcounter}
+\newcount\c_syst_helpers_mod
-\def\dosetdivision#1#2#3%
+\unexpanded\def\dosetmodulo#1#2#3%
+ {\c_syst_helpers_mod#1\divide\c_syst_helpers_mod#2\multiply\c_syst_helpers_mod#2%
+ #3#1\advance#3-\c_syst_helpers_mod}
+
+\unexpanded\def\dosetdivision#1#2#3%
{#3#1\divide#3 #2\relax}
-\def\DoMod#1by#2to#3{\dosetmodulo {#1}{#2}{#3}}
-\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}}
+\unexpanded\def\DoMod#1by#2to#3{\dosetmodulo {#1}{#2}{#3}}
+\unexpanded\def\DoDiv#1by#2to#3{\dosetdivision{#1}{#2}{#3}}
-\def\dounprotected#1\par
+\def\syst_helpers_unprotected#1\par
{#1\protect}
-\def\unprotected
- {\unprotect\dounprotected}
+\unexpanded\def\unprotected
+ {\unprotect
+ \syst_helpers_unprotected}
% awaiting the definitive implementation
@@ -6683,20 +6555,21 @@
\def\elapsedtime {\ctxcommand{elapsedtime()}}
\let\elapsedseconds \elapsedtime
-\newcount\featuretest
+\newcount\c_syst_helpers_test_feature_n
\unexpanded\def\testfeature#1#2%
- {\def\dotestfeature
- {\advance\featuretest \plusone
- \ifnum\featuretest>#1\else#2\expandafter\dotestfeature\fi}%
+ {\def\syst_helpers_test_feature_step
+ {\advance\c_syst_helpers_test_feature_n\plusone
+ \ifnum\c_syst_helpers_test_feature_n>#1\else#2\expandafter\syst_helpers_test_feature_step\fi}%
\retestfeature}
-\def\retestfeature % timer support is new per 10/5/2005
+\unexpanded\def\retestfeature % timer support is new per 10/5/2005
{\bgroup
\ifcase\interactionmode\let\wait\relax\fi
\writestatus\m!system{starting feature test}\wait
\resettimer
- \featuretest\zerocount \dotestfeature
+ \c_syst_helpers_test_feature_n\zerocount
+ \syst_helpers_test_feature_step
\writestatus\m!system{feature test done (\elapsedseconds s)}%
\wait
\egroup}
@@ -6719,7 +6592,7 @@
%D \freezedimenmacro\leftmargindistance
%D \stoptyping
-\def\freezedimenmacro#1%
+\unexpanded\def\freezedimenmacro#1%
{\edef#1{\the\dimexpr#1}}
%D The next macro negates a macro (dimension or number, or actually, whatever.
@@ -6735,191 +6608,19 @@
\def\gobbleassigndimen#1\\{}
\def\assigndimen#1#2%
- {\afterassignment\gobbleassigndimen#1=#2\!!zeropoint\\}
-
-\def\setusage#1%
- {\expandafter\let\csname#1\endcsname\iftrue}
-
-\def\resetusage#1%
- {\expandafter\let\csname#1\endcsname\iffalse}
-
-\def\ifusage#1%
- {\ifcsname#1\endcsname\else
- \resetusage{#1}%
- \fi
- \csname#1\endcsname}
-
-%D Very handy, more efficient than \type{{}}, and more readable
-%D than \type {\empty}.
-
-\let\donothing\empty
-
-% The following macros are used in XML handling.
-
-\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}}
-
-\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}%
- \afterassignment\@@dowithgrabbedstring\grabstring}
-
-\def\expifequalelse#1#2%
- {\@@ifequal#1\relax\relax\@@and#2\relax\relax\@@then}
-
-\def\@@ifequal#1#2\@@and#3%
- {\ifx#1\relax
- \ifx#3\relax
- \doubleexpandafter\@@if@@equal@@true
- \else
- \doubleexpandafter\@@if@@equal@@false
- \fi
- \else
- \ifx#3\relax
- \tripleexpandafter\@@if@@equal@@false
- \else\ifx#1#3%
- % go on
- \else
- \tripleexpandafter\@@if@@equal@@false
- \fi\fi
- \fi
- \@@ifequal#2\@@and}
-
-\def\@@if@@equal@@true #1\@@then#2#3{#2}
-\def\@@if@@equal@@false#1\@@then#2#3{#3}
+ {\afterassignment\gobbleassigndimen#1=#2\zeropoint\\}
-\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}
+\unexpanded\def\appended#1#2#3{\expandafter#1\expandafter#2\expandafter{#2#3}}
+\unexpanded\def\appendvalue #1{\expandafter\appended\expandafter \def\csname#1\endcsname}
+\unexpanded\def\appendgvalue#1{\expandafter\appended\expandafter\gdef\csname#1\endcsname}
-\def\prepended#1#2#3%
- {\scratchtoks{#3}%
+\unexpanded\def\prepended#1#2#3%
+ {\t_syst_helpers_scratch{#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,
-%D compresscommacommand,compresscommalist,compressedcommalist,
-%D reversecommacommand,reversecommalist,reversedcommalist}
-%D
-%D The following two list processing macros are needed by Taco's
-%D bibliography module. The numbers compressor converts the
-%D list in a list of ranges. The normal compressor remove duplicate
-%D and empty entries.
-%D
-%D This is now obsolete (and more a \LUA\ thing anyway).
-
-\def\compresscommalistnrs[#1]%
- {\let\compressedlist\empty
- \!!counta\maxdimen
- \!!countb\maxdimen
- \processcommalist[#1]\docompresslistnrs
- \ifnum\!!counta=\maxdimen\else\dodocompresslistnrs\fi}
-
-\def\compresscommacommandnrs[#1]%
- {\normalexpanded{\noexpand\compresscommalistnrs[#1]}}
-
-\def\docompresslistnrs#1%
- {\edef\commalistelement{#1}%
- \ifx\commalistelement\empty\else
- \ifnum\!!counta=\maxdimen
- \!!counta\commalistelement\relax
- \!!countb\!!counta
- \else
- \advance\!!countb\plusone
- \ifnum\commalistelement>\!!countb
- \advance\!!countb\minusone
- \dodocompresslistnrs
- \!!counta\commalistelement\relax
- \!!countb\!!counta
- \fi
- \fi
- \fi}
-
-\def\dodocompresslistnrs
- {\edef\compressedlist
- {\ifx\compressedlist\empty\else\compressedlist,\fi
- {\the\!!counta}{\ifnum\!!countb>\!!counta\the\!!countb\fi}}}
-
-%D \def\test#1{{\tttf#1->\compresscommalistnrs[#1]\defconvertedcommand\ascii\compressedlist\ascii}}
-%D \startlines
-%D \test{}
-%D \test{1}
-%D \test{1,3}
-%D \test{1,3,4}
-%D \test{1,3,3,4,5}
-%D \test{1,3,3,4,5,8}
-%D \test{1,3,3,4,5,5,8,10}
-%D \test{1,3,4,5,8,10,11}
-%D \test{1,,3,,4,,5,,8,,10,,11,}
-%D \stoplines
-
-\def\compresscommalist[#1]%
- {\let\compressedlist\empty
- \let\!!stringa\empty
- \processcommalist[#1]\docompresslist}
-
-\def\compresscommacommand[#1]%
- {\normalexpanded{\noexpand\compresscommalist[#1]}}
-
-\def\docompresslist#1%
- {\edef\commalistelement{#1}%
- \ifx\commalistelement\empty \else
- \ifx\!!stringa\commalistelement \else
- \ifx\compressedlist\empty
- \def\compressedlist{#1}%
- \else
- \appended\def\compressedlist{,#1}%
- \fi
- \let\!!stringa\commalistelement
- \fi
- \fi}
-
-%D \def\test#1{{\tttf#1->\compresscommalist[#1]\defconvertedcommand\ascii\compressedlist\ascii}}
-%D \startlines
-%D \test{}
-%D \test{1}
-%D \test{1,3}
-%D \test{1,3,4}
-%D \test{1,3,3,4,5}
-%D \test{1,3,3,4,5,8}
-%D \test{1,3,3,4,5,5,8,10}
-%D \test{1,3,4,5,8,10,11}
-%D \test{1,,3,,4,,5,,8,,10,,11,}
-%D \stoplines
-
-\def\reversecommalist[#1]%
- {\let\reversedlist\empty
- \processcommalist[#1]\doreverselist}
+ {\expandafter\the\expandafter\t_syst_helpers_scratch#2}}
-\def\doreverselist#1%
- {\ifx\reversedlist\empty
- \def\reversedlist{#1}%
- \else
- \prepended\def\reversedlist{#1,}%
- \fi}
-
-\def\reversecommacommand[#1]%
- {\normalexpanded{\noexpand\reversecommalist[#1]}}
-
-%D \def\test#1{{\tttf#1->\reversecommalist[#1]\defconvertedcommand\ascii\reversedlist\ascii}}
-%D \startlines
-%D \test{}
-%D \test{1}
-%D \test{1,3}
-%D \test{1,3,4}
-%D \test{1,3,3,4,5}
-%D \test{1,3,3,4,5,8}
-%D \test{1,3,3,4,5,5,8,10}
-%D \test{1,3,4,5,8,10,11}
-%D \test{1,,3,,4,,5,,8,,10,,11,}
-%D \stoplines
+\unexpanded\def\prependvalue #1{\expandafter\prepended\expandafter \def\csname#1\endcsname}
+\unexpanded\def\prependgvalue#1{\expandafter\prepended\expandafter\gdef\csname#1\endcsname}
%D \macros
%D {dowithrange}
@@ -6927,44 +6628,11 @@
%D This one is for Mojca Miklavec, who made me aware of the fact that
%D \type {page-imp.tex} was not the best place to hide it.
-\def\dowithrange#1#2% #2 takes number
+\unexpanded\def\dowithrange#1#2% #2 takes number
{\splitstring#1\at:\to\fromrange\and\torange
\ifx\torange\empty\let\torange\fromrange\fi
\dostepwiserecurse\fromrange\torange1{#2{\recurselevel}}}
-
-%D \macros {uncompresslist}
-%D
-%D When given a list like \type{1,4-7,9} as argument, this macro
-%D will store the expanded commalist in \type{\uncompressedlist}.
-%D
-%D \startbuffer
-%D \def\MojcaHasToDoTheTasks[#1]#2%
-%D {{\uncompresslist[#1]%
-%D \def\processitem##1{I have to do ##1 #2\par}%
-%D \processcommacommand[\uncompressedlist]\processitem}}
-%D
-%D \MojcaHasToDoTheTasks [1-4,7,9-11] {until tomorrow}
-%D \stopbuffer
-%D
-%D Here is an example of how to use \type {\uncompresslist}:
-%D \typebuffer
-%D
-%D The output of this is:
-%D
-%D \getbuffer
-\def\uncompresslist[#1]% by TH
- {\let\uncompressedlist\empty
- \def\docompressedlistitem##1-##2-%
- {\expandafter\dorecurse\expandafter
- {\the\numexpr1+##2-##1\relax}%
- {\expandafter\appendtocommalist\expandafter{\the\numexpr##1-1+####1\relax}\uncompressedlist}}%
- \def\douncompresslist##1%
- {\doifinstringelse{-}{##1}
- {\docompressedlistitem##1-}
- {\appendtocommalist{##1}\uncompressedlist}}%
- \processcommalist[#1]\douncompresslist}
-
%D \macros
%D {ignoreimplicitspaces}
%D
@@ -6977,7 +6645,7 @@
%D
%D \typebuffer \getbuffer
-\def\ignoreimplicitspaces
+\unexpanded\def\ignoreimplicitspaces
{\doifnextcharelse\relax\relax\relax}
%D \macros
@@ -6985,74 +6653,39 @@
%D
%D Not that sophisticated but sometimes users (like in metafun).
-\def\doprocesswords#1 #2\od
- {\doifsomething{#1}{\processword{#1} \doprocesswords#2 \od}}
-% {\doifsomething{\detokenize{#1}}{\processword{#1} \doprocesswords#2 \od}} % to be tested
+\def\syst_helpers_process_word#1 #2\_e_o_w_
+ {\doifsomething{#1}{\processword{#1} \syst_helpers_process_word#2 \_e_o_w_}}
\def\processwords#1%
- {\doprocesswords#1 \od}% no \unskip
+ {\syst_helpers_process_word#1 \_e_o_w_}% no \unskip
\let\processword\relax
-% new
-%
-% \startnointerference
-% all kind of code
-% \stopnointerference
+%D \macros
+%D {startnointerference}
+%D
+%D \starttyping
+%D \startnointerference
+%D all kind of code
+%D \stopnointerference
+%D \stoptyping
-\newbox\nointerferencebox
+\newbox\b_syst_helpers_no_interference
\unexpanded\def\startnointerference % not even grouped !
- {\setbox\nointerferencebox\vbox
+ {\setbox\b_syst_helpers_no_interference\vbox
\bgroup}
\unexpanded\def\stopnointerference
{\egroup
- \setbox\nointerferencebox\emptybox}
-
-% \def\appendtovaluelist#1#2%
-% {\ifcsname#1\endcsname
-% \expandafter\ifx\csname#1\endcsname\empty
-% \expandafter\def\csname#1\endcsname{#2}%
-% \else
-% \expandafter\def\csname#1\expandafter\expandafter\expandafter\endcsname
-% \expandafter\expandafter\expandafter{\csname#1\endcsname,#2}%
-% \fi
-% \else
-% \expandafter\def\csname#1\endcsname{#2}%
-% \fi}
-%
-% or
-%
-% \def\appendtovaluelist#1%
-% {\ifcsname#1\endcsname
-% \expandafter\ifx\csname#1\endcsname\empty
-% \expandafter\noappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname
-% \else
-% \expandafter\doappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname
-% \fi
-% \else
-% \expandafter\noappendtovaluelist\csname#1\expandafter\endcsname
-% \fi}
-
-% \def\doappendtovaluelist#1#2{\expandafter\def\expandafter#1\expandafter{#1,#2}}
-% \def\noappendtovaluelist#1#2{\def#1{#2}}
-
-% \appendtovaluelist{mylist}{aap}
-% \appendtovaluelist{mylist}{noot}
-% \appendtovaluelist{mylist}{mies}
-
-% \showvalue{mylist}
+ \setbox\b_syst_helpers_no_interference\emptybox}
%D A variant for \type {\executeifdefined}:
-% \def\expandcheckedcsname#1#2#3%
-% {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
-
\def\expandcheckedcsname#1#2% #2 is often a \xxxparameter so let's expand it once
- {\normalexpanded{\noexpand\doexpandcheckedcsname{#1}{#2}}}
+ {\normalexpanded{\noexpand\syst_helpers_expand_checked_csname{#1}{#2}}}
-\def\doexpandcheckedcsname#1#2#3%
+\def\syst_helpers_expand_checked_csname#1#2#3%
{\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}
%D Signal. Some fonts have a char0 rendering so we need to make sure that it
@@ -7060,7 +6693,41 @@
\unexpanded\def\signalcharacter{\char\zerocount} % \zwj
-%D Here are some nasty helpers:
+%D A few secial variants of commands defined here. Some more will be moved here (e.g.
+%D from table modules.
+
+\def\dodirectdoubleempty#1#2% used in math (lookahead issues)
+ {\ifx#2[%
+ \expandafter\syst_helpers_direct_double_empty_one_yes
+ \else
+ \expandafter\syst_helpers_direct_double_empty_one_nop
+ \fi#1#2}
+
+\def\syst_helpers_direct_double_empty_one_yes#1[#2]#3%
+ {\ifx#3[\else\expandafter\syst_helpers_direct_double_empty_two_nop\fi#1[#2]#3}
+
+\def\syst_helpers_direct_double_empty_one_nop#1{#1[][]}
+\def\syst_helpers_direct_double_empty_two_nop#1[#2]{#1[#2][]}
+
+%D Used in math definitions (in an type {\edef}):
+
+%D \startbuffer
+%D [\docheckedpair{}]
+%D [\docheckedpair{a}]
+%D [\docheckedpair{a,b}]
+%D [\docheckedpair{a,b,c}]
+%D \stopbuffer
+%D
+%D \typebuffer \startlines \getbuffer \stoplines
+
+\def\docheckedpair#1%
+ {\syst_helpers_checked_pair#1,,\_o_e_p_}
+
+\def\syst_helpers_checked_pair#1,#2,#3\_o_e_p_
+ {#1,#2}
+
+%D Here are some nasty helpers. They can be used to fill often expanded token
+%D lists efficiently (see tabulate for an example).
\def\constantnumber#1%
{\ifcase#1\zerocount
@@ -7111,8 +6778,53 @@
{#1}%
\fi}
-%D These can be used when constructing often reused token lists,
-%D as we do with tabulates.
+% %D Maybe some day (moved from cont-new):
+% %D
+% %D \starttyping
+% %D \the\dimexpr(\dimchoice {7pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+% %D \the\dimexpr(\dimchoice{11pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+% %D \the\dimexpr(\dimchoice{14pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
+% %D \stoptyping
+%
+% \def\syst_helpers_choice_finish#1\empty{}
+%
+% \def\syst_helpers_choice_dim#1#2#3%
+% {\ifdim#1#2%
+% #3\expandafter\syst_helpers_choice_finish
+% \else
+% \expandafter\syst_helpers_choice_dim
+% \fi{#1}}
+%
+% \def\syst_helpers_choice_num#1#2#3%
+% {\ifnum#1#2%
+% #3\expandafter\syst_helpers_choice_finish
+% \else
+% \expandafter\syst_helpers_choice_num
+% \fi{#1}}
+%
+% \def\dimchoice#1#2{\syst_helpers_choice_dim{#1}#2{=#1}{#1}\empty}
+% \def\numchoice#1#2{\syst_helpers_choice_num{#1}#2{=#1}{#1}\empty}
+
+%D \macros
+%D {getsubstring}
+%D \startbuffer
+%D
+%D \getsubstring{4}{}{Who Wants This}
+%D \getsubstring{4}{9}{Who Wants This}
+%D \getsubstring{9}{-2}{Who Wants This}
+%D \getsubstring{1}{5}{Who Wants This}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+% expandable:
+
+%def\getsubstring#1#2#3{\cldcontext{utf.sub([[#3]],tonumber("#1"),tonumber("#2"))}}
+\def\getsubstring#1#2#3{\ctxcommand{getsubstring(\!!bs#3\!!es,"#1","#2")}}
\protect \endinput
@@ -7174,3 +6886,37 @@
% nothing
% }
% \stopchoice
+
+% \def\appendtovaluelist#1#2%
+% {\ifcsname#1\endcsname
+% \expandafter\ifx\csname#1\endcsname\empty
+% \expandafter\def\csname#1\endcsname{#2}%
+% \else
+% \expandafter\def\csname#1\expandafter\expandafter\expandafter\endcsname
+% \expandafter\expandafter\expandafter{\csname#1\endcsname,#2}%
+% \fi
+% \else
+% \expandafter\def\csname#1\endcsname{#2}%
+% \fi}
+%
+% or
+%
+% \def\appendtovaluelist#1%
+% {\ifcsname#1\endcsname
+% \expandafter\ifx\csname#1\endcsname\empty
+% \expandafter\noappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname
+% \else
+% \expandafter\doappendtovaluelist\csname#1\expandafter\expandafter\expandafter\endcsname
+% \fi
+% \else
+% \expandafter\noappendtovaluelist\csname#1\expandafter\endcsname
+% \fi}
+%
+% \def\doappendtovaluelist#1#2{\expandafter\def\expandafter#1\expandafter{#1,#2}}
+% \def\noappendtovaluelist#1#2{\def#1{#2}}
+%
+% \appendtovaluelist{mylist}{aap}
+% \appendtovaluelist{mylist}{noot}
+% \appendtovaluelist{mylist}{mies}
+%
+% \showvalue{mylist}
diff --git a/tex/context/base/syst-fnt.mkiv b/tex/context/base/syst-fnt.mkiv
index f5c9ea349..625b952b7 100644
--- a/tex/context/base/syst-fnt.mkiv
+++ b/tex/context/base/syst-fnt.mkiv
@@ -38,7 +38,7 @@
\def\mathsubcombined {\fontdimen17 } % to be remapped
\def\mathaxisheight {\fontdimen22 } % to be remapped
-\def\currentspaceskip {\interwordspace\!!plus\interwordstretch\!!minus\interwordshrink\relax}
+\def\currentspaceskip {\interwordspace\s!plus\interwordstretch\s!minus\interwordshrink\relax}
\def\mathstacktotal {\dimexpr\Umathstacknumup\scriptstyle+\Umathstackdenomdown\scriptstyle\relax}
\def\mathstackvgap {\Umathstackvgap\scriptstyle}
diff --git a/tex/context/base/syst-gen.mkii b/tex/context/base/syst-gen.mkii
index bb0f54d11..8b71b77d5 100644
--- a/tex/context/base/syst-gen.mkii
+++ b/tex/context/base/syst-gen.mkii
@@ -657,6 +657,11 @@
\def\resetvalue #1{\expandafter\let\csname#1\endcsname\empty}
\def\ignorevalue#1#2{\expandafter\let\csname#1\endcsname\empty}
+\def\setuvalue #1{\normalprotected\expandafter \def\csname#1\endcsname}
+\def\setuevalue #1{\normalprotected\expandafter\edef\csname#1\endcsname}
+\def\setugvalue #1{\normalprotected\expandafter\gdef\csname#1\endcsname}
+\def\setuxvalue #1{\normalprotected\expandafter\xdef\csname#1\endcsname}
+
%D \macros
%D {globallet,glet}
%D
diff --git a/tex/context/base/syst-ini.mkiv b/tex/context/base/syst-ini.mkiv
index 983bedc52..1c87c4ed4 100644
--- a/tex/context/base/syst-ini.mkiv
+++ b/tex/context/base/syst-ini.mkiv
@@ -11,16 +11,14 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D We used to load plain \TEX\ in a special way, but redefining
-%D a couple of primitives so that for instance font loading was
-%D ignored. For those interested, this loader is found in
-%D \type {syst-tex.tex}. Some of the comment's are Don Knuth's
-%D and more of it can be found in the plain \TEX\ format.
-
-%D Characters can have special states, that can be triggered
-%D by setting their category coded. Some are preset, others
-%D are to be set as soon as possible, otherwise we cannot
-%D define any useful macros.
+%D We used to load plain \TEX\ in a special way, but redefining a couple of
+%D primitives so that for instance font loading was ignored. For those interested,
+%D this loader is found in \type {syst-tex.tex}. Some of the comment's are Don
+%D Knuths and more of it can be found in the plain \TEX\ format.
+%D
+%D Characters can have special states, that can be triggered by setting their
+%D category coded. Some are preset, others are to be set as soon as possible,
+%D otherwise we cannot define any useful macros.
%catcode`\^^@ = 9 % ascii null is ignored
%catcode`\\ = 0 % backslash is TeX escape character
@@ -58,8 +56,7 @@
\catcode`\^^Z=9
-%D It makes sense to know what engine we're running so let's
-%D try to deduce it.
+%D It makes sense to know what engine we're running so let's try to deduce it.
\chardef\unknownengine = 0
\chardef\pdftexengine = 1
@@ -117,16 +114,15 @@
}
\fi
-%D \ETEX\ has a not so handy way of telling you the version number,
-%D i.e. the revision number has a period in it:
+%D \ETEX\ has a not so handy way of telling you the version number, i.e. the revision
+%D number has a period in it:
\long\def\gobbleoneargument#1{} % will be defined later on anyway
\mathchardef\etexversion = \numexpr\eTeXversion*100+\expandafter\gobbleoneargument\eTeXrevision\relax
-%D First we define a simplified version of the \CONTEXT\
-%D protection mechanism. Later we will implement a better
-%D variant.
+%D First we define a simplified version of the \CONTEXT\ protection mechanism.
+%D Later we will implement a better variant.
\def\unprotect
{\edef\protect
@@ -149,18 +145,21 @@
\let\bgroup={
\let\egroup=}
-%D Allocation of registers is done slightly different than in plain
-%D \TEX. First of all we use different reserved counters. We also
-%D don't implement a family handler because users are not supposed
-%D to implement their own math. We reserve the lowest 31 registers
-%D for scratch purposes. Keep in mind that in the core engine
-%D some registers are reserved: counters 0 upto 9, and counter 255.
+%D \macros
+%D {normalbgroup,normalgroup}
%D
-%D As with plain \TEX\ we recommend that macro designers always use
-%D \type {\global} assignments with respect to registers numbered 1,
-%D 3, 5 \unknown\ 31, and always non||\type {\global} assignments
-%D with respect to registers 0, 2, 4, \unknown\ 30. This will prevent
-%D \quote {save stack buildup} that might otherwise occur.
+%D No comment.
+
+%D Allocation of registers is done slightly different than in plain \TEX. First of
+%D all we use different reserved counters. We also don't implement a family handler
+%D because users are not supposed to implement their own math. We reserve the lowest
+%D 31 registers for scratch purposes. Keep in mind that in the core engine some
+%D registers are reserved: counters 0 upto 9, and counter 255.
+%D
+%D As with plain \TEX\ we recommend that macro designers always use \type {\global}
+%D assignments with respect to registers numbered 1, 3, 5 \unknown\ 31, and always
+%D non||\type {\global} assignments with respect to registers 0, 2, 4, \unknown\ 30.
+%D This will prevent \quote {save stack buildup} that might otherwise occur.
%D
%D We reserve some registers for special (management) purposes:
@@ -212,11 +211,10 @@
\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
-%D counters 0 upto 9 and the pagebox is 255. Users can use the
-%D scratch registers upto 31 without problem but all others are
-%D reserved.
+%D So, effectively we start allocating from 256 and upwards. The inserts sit in the
+%D range 128 upto 254. Page numbers use the counters 0 upto 9 and the pagebox is
+%D 255. Users can use the scratch registers upto 31 without problem but all others
+%D are reserved.
\let\wlog\gobbleoneargument % Let's get rid of this one.
@@ -254,12 +252,11 @@
%newlinechar=10 \def\outputnewlinechar{\rawcharacter{10}}
\newlinechar=10 \edef\outputnewlinechar{^^J}
-%D One reason to start high with allocation is that it permits us to
-%D allocate consecutive ranges more easily, for instance if for \MPLIB\
-%D we want to allocate a continuous range of boxes. It also permits us
-%D to do a proper upward allocation for inserts. The current code
-%D evolved from code that dealt with older engines but as all engines
-%D now provide many registers we removed all traces.
+%D One reason to start high with allocation is that it permits us to allocate
+%D consecutive ranges more easily, for instance if for \MPLIB\ we want to allocate a
+%D continuous range of boxes. It also permits us to do a proper upward allocation
+%D for inserts. The current code evolved from code that dealt with older engines but
+%D as all engines now provide many registers we removed all traces.
\ifdefined\writestatus \else
\normalprotected\def\writestatus#1#2{\immediate\write16{#1: #2}}
@@ -286,29 +283,27 @@
\fi\fi
#1#2#3#4#5}
-%D Since the number of chars exceed 256 now, we can use \type
-%D {\chardef} instead of the more limited \type {\mathchardef}.
+%D Since the number of chars exceed 256 now, we can use \type {\chardef} instead of
+%D the more limited \type {\mathchardef}.
\ifnum\texengine>\pdftexengine
\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
-%D supposed to use the attributes directly but always allocate then
-%D first. For instance attribute~0 is reserved for special purposes
-%D (this might change). Attributes in the range 128-1023 are private
-%D and should not be touched.
+%D Attributes are something very \LUATEX. In \CONTEXT\ you are not supposed to use
+%D the attributes directly but always allocate then first. For instance attribute~0
+%D is reserved for special purposes (this might change). Attributes in the range
+%D 128-1023 are private and should not be touched.
\ifnum\texengine=\luatexengine
\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. This macro is never used
-%D in \CONTEXT.
+%D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a trick to force
+%D strings instead of tokens that take more memory. It's a trick to trick to force
+%D strings. This macro is never used in \CONTEXT.
\normalprotected\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
@@ -318,8 +313,8 @@
%D scratchbox,
%D scratchtoks}
%D
-%D We now define a few scratch registers, so that successive
-%D loads at least have some available.
+%D We now define a few scratch registers, so that successive loads at least have
+%D some available.
\newcount \scratchcounter \newcount \globalscratchcounter
\newdimen \scratchdimen \newdimen \globalscratchdimen
@@ -343,21 +338,49 @@
\newdimen\scratchwidth
\newdimen\scratchheight
\newdimen\scratchdepth
+
\newdimen\scratchoffset
+\newdimen\scratchleftoffset
+\newdimen\scratchrightoffset
+\newdimen\scratchtopoffset
+\newdimen\scratchbottomoffset
+
\newdimen\scratchdistance
+
\newdimen\scratchhsize
\newdimen\scratchvsize
+\newdimen\scratchxoffset
+\newdimen\scratchyoffset
+\newdimen\scratchhoffset
+\newdimen\scratchvoffset
+
+\newdimen\scratchxposition
+\newdimen\scratchyposition
+
+\newcount\scratchnx
+\newcount\scratchny
+
+\newcount\scratchmx
+\newcount\scratchmy
+
+\newdimen\scratchleftskip
+\newdimen\scratchrightskip
+\newdimen\scratchtopskip
+\newdimen\scratchbottomskip
+
%D More allocations:
-\newskip \zeroskip \zeroskip = 0pt plus 0pt minus 0pt
-\newdimen\zeropoint \zeropoint = 0pt
-\newdimen\onepoint \onepoint = 1pt
-\newdimen\halfapoint \halfapoint = 0.5pt
-\newdimen\maxdimen \maxdimen = 16383.99999pt
-\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
+\newmuskip\zeromuskip \zeromuskip = 0mu
+\newmuskip\onemuskip \onemuskip = 1mu
\let\points \onepoint
\let\halfpoint\halfapoint
@@ -410,8 +433,8 @@
\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}:
+%D We prefer the more readable variant than in plain \TEX. User should only
+%D use \type {\emptybox}:
\newbox\voidbox % public
@@ -425,8 +448,19 @@
\let\leavevmode\unvoidbox % we prefer to use \dontleavehmode
-%D Some expected plain variants follow. We don't reuse registers
-%D because we don't want clashes.
+%D \macros
+%D {dontcomplain}
+%D
+%D We need this one soon:
+
+\normalprotected\def\dontcomplain
+ {\hbadness\plustenthousand
+ \vbadness\plustenthousand
+ \hfuzz \maxdimen
+ \vfuzz \maxdimen}
+
+%D Some expected plain variants follow. We don't reuse registers because we
+%D don't want clashes.
\newdimen\p@ \p@ \onepoint
\newcount\m@ne \m@ne \minusone
@@ -440,8 +474,8 @@
\newbox \voidb@x
\newtoks \toks@
-%D We define \type {\newif} a la plain \TEX, but will
-%D redefine it later. As Knuth says:
+%D We define \type {\newif} a la plain \TEX, but will redefine it later. As
+%D Knuth says:
%D
%D \startnarrower
%D And here's a different sort of allocation: for example,
@@ -450,8 +484,7 @@
%D \newif\iffoo
%D \stoptyping
%D
-%D creates \type {\footrue}, \type {\foofalse} to go
-%D with \type {\iffoo}.
+%D creates \type {\footrue}, \type {\foofalse} to go with \type {\iffoo}.
%D \stopnarrower
\normalprotected\def\newif#1%
@@ -479,8 +512,16 @@
\ifdefined\htdp \else \def\htdp#1{\dimexpr\ht#1+\dp#1\relax} \fi
-%D The catcode constants will be redefined in later catcode
-%D related modules but they can be used in the same way.
+%D A few shortcuts:
+
+\normalprotected\def\glet {\global \let }
+\normalprotected\def\udef {\normalprotected\def }
+\normalprotected\def\ugdef{\normalprotected\gdef}
+\normalprotected\def\uedef{\normalprotected\edef}
+\normalprotected\def\uxdef{\normalprotected\xdef}
+
+%D The catcode constants will be redefined in later catcode related modules
+%D but they can be used in the same way.
\chardef\escapecatcode = 0
\chardef\begingroupcatcode = 1
@@ -499,6 +540,11 @@
\chardef\commentcatcode = 14
\chardef\invalidcatcode = 15
+%D For a while we keep the following, as systems like tikz need it. Best
+%D not use that one \CONTEXT.
+
+\let\active\activecatcode
+
%D Constants to be used with \type {\currentgrouptype}.
\chardef\bottomlevelgroupcode = 0
@@ -527,13 +573,12 @@
\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
-%D still -1 .. 15 and glyph nodes have number 0 (used to be char
-%D node) and ligature nodes are mapped to 7. That way macro packages
-%D can use the same symbolic names as in traditional \ETEX. Keep in
-%D mind that the internal node numbers are different and that there
-%D are more node types that 15.
+%D Constants to be used with \type {\lastnodetype}. The \type {\lastnodetype}
+%D primitive is \ETEX\ compliant. The valid range is still -1 .. 15 and glyph nodes
+%D have number 0 (used to be char node) and ligature nodes are mapped to 7. That way
+%D macro packages can use the same symbolic names as in traditional \ETEX. Keep in
+%D mind that the internal node numbers are different and that there are more node
+%D types that 15.
\chardef\charnodecode = 0
\chardef\hlistnodecode = 1
@@ -552,8 +597,8 @@
\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.
+%D Constants to be used with \type {\currentiftype}. I wonder if we will ever
+%D use these in \CONTEXT.
\chardef\charifcode = 1
\chardef\catifcode = 2
@@ -576,11 +621,11 @@
\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.
+%D Of course we want even bigger log files, so we copied this from the \ETEX\
+%D source files.
%D
-%D When watching such logs, beware of nasty side effects of
-%D \type {\scantokens}, as in:
+%D When watching such logs, beware of nasty side effects of \type {\scantokens},
+%D as in:
%D
%D \starttyping
%D \bgroup
@@ -641,14 +686,13 @@
\ifdefined\normalinput \else \let\normalinput\input \fi
-%D We don't like outer commands, and we always want access
-%D to the original \type {\input} primitive.
+%D We don't like outer commands, and we always want access to the original
+%D \type {\input} primitive.
\let\normalouter\outer \def\outer{} % no longer \relax
-%D To circumvent dependencies, we can postpone certain
-%D initializations to dumping time, by appending them to the
-%D \type {\everydump} token register.
+%D To circumvent dependencies, we can postpone certain initializations to
+%D dumping time, by appending them to the \type {\everydump} token register.
\ifdefined\normaldump \else \let\normaldump\dump \fi
@@ -669,11 +713,10 @@
%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 \TEX's lacks boolean variables, although the \PLAIN\ format implements \type
+%D {\newif}. The main disadvantage of this scheme is that it takes three hash table
+%D entries. A more memory saving alternative is presented here. A conditional is
+%D defined by:
%D
%D \starttyping
%D \newconditional\doublesided
@@ -699,9 +742,8 @@
%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:
+%D Such an implementation gives problems with nested conditionals. The next
+%D implementation is about as fast and just as straightforward:
\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef
\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef
@@ -717,8 +759,8 @@
%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.
+%D Let's be complete and also introduce some definers. These are not mandate
+%D but handy for grepping.
\normalprotected\def\newmacro #1{\let#1\empty}
\normalprotected\def\setnewmacro#1{\let#1}
@@ -727,17 +769,15 @@
\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 It would be handy to have a primitive \unless\ifcase because then we could
+%D use nicer values. Anyhow, this conditional code used to be in the \type
+%D {syst-aux} module but is now promoted 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 The next macro is both cosmetic and byte saving. It is pretty \type
+%D {\if}||safe too. It can be used in cases like:
%D
%D \starttyping
%D \ifzeropt \somedimen ... \else ... \fi
@@ -785,7 +825,23 @@
\def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi}
-%D Now come a few macros that might be needed in successive loading:
+%D Now come a few macros that might be needed in successive loading. We redefine the
+%D \type {\par} primitive pretty soon so that we get the equivalents right.
+
+% too tricky: \par is use more often than a par starts so we have too much change
+% that we get assymetrical behaviour
+%
+% \newtoks\everyendpar
+%
+% \normalprotected\def\endpar{\the\everyendpar\normalpar}
+% \normalprotected\def\par {\endpar}
+%
+% \normalprotected\def\reseteverypar
+% {\everypar \emptytoks
+% \everyendpar\emptytoks}
+
+\normalprotected\def\reseteverypar
+ {\everypar\emptytoks}
\let\endgraf\par
\let\endline\cr
@@ -794,9 +850,8 @@
\def\empty{}
\def\null {\hbox{}}
-%D The following two might be overloaded later on but some modules need
-%D then earlier. These functionality is reflected in the name and will not
-%D change.
+%D The following two might be overloaded later on but some modules need then
+%D earlier. These functionality is reflected in the name and will not change.
\bgroup
\catcode`\^^M=\activecatcode%
@@ -813,16 +868,15 @@
\let\endoflinetoken=^^M
-%D Also needed might be a simple loop structure and we borrow
-%D plain \TEX's one as it is often expected to be present and
-%D it is about the fastest you can get. Beware: this macro
-%D does not support nested loops. We use a namespace prefix
-%D \type {@@pln}.
+%D Also needed might be a simple loop structure and we borrow plain \TEX's one
+%D as it is often expected to be present and it is about the fastest you can
+%D get. Beware: this macro does not support nested loops. We use a namespace
+%D prefix \type {@@pln}.
\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):
+%D The following makes \type {\loop} \unknown\ \type {\if} \unknown\ \type
+%D {\repeat} skippable (clever trick):
\let\repeat\fi % so both \loop and \repeat are reserved words!
@@ -842,23 +896,22 @@
\def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\fi}
-%D We don't define a real output routine yet but at least get rid
-%D of pages:
+%D We don't define a real output routine yet but at least get rid of pages:
\output{\shipout\box\normalpagebox}
-%D Although we don't add pagenumbers yet we alias the default
-%D register used for counting pages:
+%D Although we don't add pagenumbers yet we alias the default register used
+%D for counting pages:
\countdef\pageno=0 \pageno=1 % first page is number 1
-%D Beside the raw counter \type {\pageno} the \type {\folio}
-%D macro provides the value.
+%D Beside the raw counter \type {\pageno} the \type {\folio} macro provides
+%D the value.
\def\folio{\the\pageno} % kind of expected and therefore reserved
-%D The following registers are kind of standard and (for the moment)
-%D we define them here. This might change.
+%D The following registers are kind of standard and (for the moment) we define
+%D them here. This might change.
\newskip \bigskipamount \bigskipamount = 12pt plus 4pt minus 4pt
\newskip \medskipamount \medskipamount = 6pt plus 2pt minus 2pt
@@ -893,9 +946,8 @@
\spanomit \advance\mscount\minusone
\repeat}
-%D The next section deals with selective definitions in
-%D later modules. One can of course use the \type {\texengine}
-%D number that we defined earlier instead.
+%D The next section deals with selective definitions in later modules. One can of
+%D course use the \type {\texengine} number that we defined earlier instead.
\bgroup \obeylines
\gdef\pickupSOMETEX#1%
@@ -927,19 +979,19 @@
\fi
%D \macros
-%D {bindprimitive}
+%D {bindprimitive}
%D
-%D We can remap primitives (which is needed because of changes in
-%D for instance \PDFTEX).
+%D We can remap primitives (which is needed because of changes in for instance
+%D \PDFTEX).
\def\bindprimitive#1 #2 % new old
{\ifcsname#1\endcsname \else \ifcsname#2\endcsname
\expandafter\let\csname#1\expandafter\endcsname\csname#2\endcsname
\fi \fi}
-%D Because \XETEX\ also implements some \PDFTEX\ functionality, we take
-%D care of this here instead of a dedicated module. Later modules need
-%D to handle the undefined cases.
+%D Because \XETEX\ also implements some \PDFTEX\ functionality, we take care of this
+%D here instead of a dedicated module. Later modules need to handle the undefined
+%D cases.
%D These messy checks will disappear.
@@ -997,8 +1049,8 @@
\newif\ifproductionrun
-%D We need to make sure that we start up in \DVI\ mode, so,
-%D after testing for running \PDFTEX, we default to \DVI.
+%D We need to make sure that we start up in \DVI\ mode, so, after testing for running
+%D \PDFTEX, we default to \DVI.
\ifx\pdftexversion\undefined \newcount\pdfoutput \fi \pdfoutput=0
@@ -1044,15 +1096,14 @@
\let\synctex\undefined \newcount\synctex
-%D We get rid of the funny \TEX\ offset defaults of one
-%D inch by setting them to zero.
+%D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero.
-\voffset \zeropoint \newdimen\voffset % prevent messing up
-\hoffset \zeropoint \newdimen\hoffset % prevent messing up
+\voffset\zeropoint \let\voffset\relax \newdimen\voffset % prevent messing up
+\hoffset\zeropoint \let\hoffset\relax \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:
+%D While cleaning this code up a bit I was listening to Heather Nova's \CD\ Redbird.
+%D The first song on that \CD\ ends with a few lines suitable for ending this
+%D initialization module:
%D
%D \startlines
%D And there's so much I can do for you
@@ -1065,7 +1116,6 @@
%D Come inside
%D \stoplines
%D
-%D So let's see what \TEX\ can do now that we've opened up
-%D the basic machinery.
+%D So let's see what \TEX\ can do now that we've opened up the basic machinery.
\protect \endinput
diff --git a/tex/context/base/syst-lua.lua b/tex/context/base/syst-lua.lua
index f735b1962..ef524c339 100644
--- a/tex/context/base/syst-lua.lua
+++ b/tex/context/base/syst-lua.lua
@@ -16,14 +16,17 @@ commands = commands or { }
function commands.writestatus(...) logs.status(...) end -- overloaded later
--- 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)
+-- contextsprint(prtcatcodes,[[\ui_fo]]) -- firstofonearguments
+-- contextsprint(prtcatcodes,[[\ui_go]]) -- gobbleonearguments
+-- contextsprint(prtcatcodes,[[\ui_ft]]) -- firstoftwoarguments
+-- contextsprint(prtcatcodes,[[\ui_st]]) -- secondoftwoarguments
+
+function commands.doifelse(b)
if b then
firstoftwoarguments()
else
@@ -47,33 +50,45 @@ function commands.doifnot(b)
end
end
-commands.testcase = testcase
-commands.doifelse = testcase
+commands.testcase = commands.doifelse -- obsolete
function commands.boolcase(b)
context(b and 1 or 0)
end
function commands.doifelsespaces(str)
- return testcase(find(str,"^ +$"))
+ if find(str,"^ +$") then
+ firstoftwoarguments()
+ else
+ secondoftwoarguments()
+ end
end
local s = lpegtsplitat(",")
local h = { }
-function commands.doifcommonelse(a,b)
+function commands.doifcommonelse(a,b) -- often the same test
local ha = h[a]
local hb = h[b]
- if not ha then ha = lpegmatch(s,a) h[a] = ha end
- if not hb then hb = lpegmatch(s,b) h[b] = hb end
- for i=1,#ha do
- for j=1,#hb do
+ if not ha then
+ ha = lpegmatch(s,a)
+ h[a] = ha
+ end
+ if not hb then
+ hb = lpegmatch(s,b)
+ h[b] = hb
+ end
+ local na = #ha
+ local nb = #hb
+ for i=1,na do
+ for j=1,nb do
if ha[i] == hb[j] then
- return testcase(true)
+ firstoftwoarguments()
+ return
end
end
end
- return testcase(false)
+ secondoftwoarguments()
end
function commands.doifinsetelse(a,b)
@@ -81,16 +96,21 @@ function commands.doifinsetelse(a,b)
if not hb then hb = lpegmatch(s,b) h[b] = hb end
for i=1,#hb do
if a == hb[i] then
- return testcase(true)
+ firstoftwoarguments()
+ return
end
end
- return testcase(false)
+ secondoftwoarguments()
end
local pattern = lpeg.patterns.validdimen
function commands.doifdimenstringelse(str)
- testcase(lpegmatch(pattern,str))
+ if lpegmatch(pattern,str) then
+ firstoftwoarguments()
+ else
+ secondoftwoarguments()
+ end
end
function commands.firstinset(str)
diff --git a/tex/context/base/syst-lua.mkiv b/tex/context/base/syst-lua.mkiv
index 0d72e4a01..004655b74 100644
--- a/tex/context/base/syst-lua.mkiv
+++ b/tex/context/base/syst-lua.mkiv
@@ -40,4 +40,11 @@
%def\luaexpr#1{\ctxlua {context(tostring(#1))}}
\def\luaexpr#1{\directlua\zerocount{context(tostring(#1))}} % wrap in global function ?
+% helpers:
+
+\def\ui_fo #1{#1}
+\def\ui_go #1{}
+\def\ui_ft#1#2{#1}
+\def\ui_st#1#2{#2}
+
\protect \endinput
diff --git a/tex/context/base/tabl-ltb.mkiv b/tex/context/base/tabl-ltb.mkiv
index 542d256f2..f7fbc0390 100644
--- a/tex/context/base/tabl-ltb.mkiv
+++ b/tex/context/base/tabl-ltb.mkiv
@@ -63,6 +63,8 @@
\newconstant\linetableheadstate
\newconstant\linetablemode
+\definesystemvariable {le} % LinetablE
+
\edef\??ler{\??le:r:}
\edef\??lec{\??le:c:}
\edef\??lew{\??le:w:}
@@ -721,10 +723,10 @@
\startlinetablerun \readfile{#1}\donothing\donothing\stoplinetablerun
\egroup}
-\protect \endinput
+\protect
+
+\continueifinputfile{tabl-ltb.mkiv}
-\doifnotmode{demo}{\endinput}
-
\setuplinetable[n=6,m={2,2,2},lines=25] % m ?
\setuplinetable[c][1] [width=2cm,background=color,backgroundcolor=red]
diff --git a/tex/context/base/tabl-mis.mkiv b/tex/context/base/tabl-mis.mkiv
new file mode 100644
index 000000000..9a0f13853
--- /dev/null
+++ b/tex/context/base/tabl-mis.mkiv
@@ -0,0 +1,288 @@
+%D \module
+%D [ file=tabl-mis,
+%D version=2012.06.28,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Miscellaneous,
+%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 / Miscellaneous}
+
+\unprotect
+
+%D \macros
+%D {somekindoftab,kindoftabposition}
+%D
+%D This macro can be used to create tabs:
+%D
+%D \starttyping
+%D \setupheadertexts[{\somekindoftab[alternative=horizontal]{\framed{\kindoftabposition}}}]
+%D \setuptexttexts [{\somekindoftab[alternative=vertical] {\framed{\kindoftabposition}}}]
+%D
+%D \starttext
+%D \showframe \dorecurse{10}{test\page}
+%D \stoptext
+%D \stoptyping
+%D
+%D (This rather old but updated code used to be in \type {core-mis.mkiv}.)
+
+\let\kindoftabposition\!!zerocount
+
+\unexpanded\def\somekindoftab
+ {\dosingleempty\typo_kindoftab}
+
+\def\typo_kindoftab[#1]%
+ {\bgroup
+ \getdummyparameters
+ [\c!alternative=\v!vertical,
+ \c!width=\textwidth,\c!height=\textheight,
+ \c!n=\lastpage,\c!m=\realpageno,
+ #1]%
+ \doifelse{\directdummyparameter\c!alternative}\v!vertical
+ {\typo_kindoftab_indeed\vbox\vskip\c!height}
+ {\typo_kindoftab_indeed\hbox\hskip\c!width }}
+
+\def\typo_kindoftab_indeed#1#2#3#4%
+ {#1 to \directdummyparameter#3 \bgroup
+ \forgetall
+ \scratchnx\directdummyparameter\c!n\relax
+ \scratchmx\directdummyparameter\c!m\relax
+ \edef\kindoftabposition{\the\scratchmx}%
+ \ifnum\scratchmx>\plusone
+ #2\zeropoint \s!plus \the\numexpr\scratchmx-\plusone \relax\s!fill\relax
+ \fi
+ #4% can use \kindoftabposition
+ \ifnum\scratchmx<\scratchnx\relax
+ #2\zeropoint \s!plus \the\numexpr\scratchnx-\scratchmx\relax\s!fill\relax
+ \fi
+ \egroup
+ \egroup}
+
+%D The following paragraphs mechanism is probably one of the oldest of
+%D \CONTEXT\ and mostly served as a table mechanism capable of dealing
+%D with paragraphs. Nowadays one can also use tabulate or natural tables.
+%D
+%D \startbuffer
+%D \defineparagraphs[sample][n=2,rule=on]
+%D
+%D \startsample
+%D first \nextsample
+%D second \nextsample
+%D third
+%D \stopsample
+%D
+%D \startsample
+%D \input tufte \nextsample
+%D \input ward \nextsample
+%D \input davis \nextsample
+%D \input zapf
+%D \stopsample
+%D
+%D \startparagraphs[sample]
+%D first \nextsample
+%D second \nextsample
+%D third
+%D \stopparagraphs
+%D
+%D \startparagraphs[sample]
+%D \startparagraphscell
+%D first
+%D \stopparagraphscell
+%D \startparagraphscell
+%D second
+%D \stopparagraphscell
+%D \startparagraphscell
+%D third
+%D \stopparagraphscell
+%D \stopparagraphs
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace{paragraphs}
+
+\installcommandhandler \??paragraphs {paragraphs} \??paragraphs
+
+\setupparagraphs
+ [\c!n=3,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance=\emwidth,
+ \c!height=\v!fit,
+ \c!width=\availablehsize,
+ \c!rule=\v!off,
+ \c!command=,
+ \c!align=,
+ \c!tolerance=\v!tolerant, % obsolete
+ \c!rulethickness=\linewidth,
+ \c!rulecolor=,
+ \c!style=,
+ \c!color=,
+ \c!top=\vss,
+ \c!bottom=\vfill]
+
+\let\typo_paragraphs_setup_saved\setupparagraphs
+
+\unexpanded\def\setupparagraphs
+ {\dotripleempty\typo_paragraphs_setup}
+
+\def\typo_paragraphs_setup[#1][#2][#3]% we are downward compatible with [each] and [1,3]
+ {\ifthirdargument
+ \doifelse{#2}\v!each
+ {\typo_paragraphs_setup_saved[#1][#3]}
+ {\def\typo_paragraphs_setup_step##1{\typo_paragraphs_setup_saved[#1:##1][#3]}%
+ \processcommalist[#2]\typo_paragraphs_setup_step}%
+ \else\ifsecondargument
+ \typo_paragraphs_setup_saved[#1][#2]%
+ \else\iffirstargument
+ \typo_paragraphs_setup_saved[#1]%
+ \fi\fi\fi}
+
+\appendtoks
+ \letvalue{\e!next \currentparagraphs}\nextparagraphs
+ \letvalue\currentparagraphs\nextparagraphs
+ \setuevalue{\e!start\currentparagraphs}{\startparagraphs[\currentparagraphs]}%
+ \letvalue{\e!stop \currentparagraphs}\stopparagraphs
+ %setuevalue{\e!setup\currentparagraph\e!endsetup}{\typo_paragraphs_setup_saved[\currentparagraphs]}%
+ \dorecurse{\paragraphsparameter\c!n}
+ {\normalexpanded{\typo_paragraphs_setup_saved[\currentparagraphs:\recurselevel][\c!width=,\s!parent=\??paragraphs\currentparagraphs]}}%
+ \typo_paragraphs_setup_saved[\currentparagraphs:1][\c!distance=\zeropoint]%
+\to \everydefineparagraphs
+
+\newcount\c_typo_paragraphs_n
+\newcount\c_typo_paragraphs_max
+\newdimen\d_typo_paragraphs_width
+\newdimen\d_typo_paragraphs_auto
+
+\unexpanded\def\startparagraphs[#1]% quite slow
+ {\bgroup % (1)
+ \edef\currentparagraphs{#1}%
+ \paragraphsparameter\c!before
+ \edef\p_width{\paragraphsparameter\c!width}%
+ \ifx\p_width\empty
+ \d_typo_paragraphs_width\availablehsize
+ \else
+ \d_typo_paragraphs_width\p_width\relax
+ \fi
+ \c_typo_paragraphs_max\paragraphsparameter\c!n\relax
+ \d_typo_paragraphs_auto\d_typo_paragraphs_width\relax
+ \scratchcounter\zerocount
+ \dorecurse\c_typo_paragraphs_max
+ {\edef\p_width{\namedparagraphsparameter{\currentparagraphs:\recurselevel}\c!width}%
+ \ifx\p_width\empty
+ \advance\scratchcounter\plusone
+ \else
+ \advance\d_typo_paragraphs_auto-\p_width\relax
+ \fi
+ \ifnum\recurselevel>\plusone
+ \advance\d_typo_paragraphs_auto-\namedparagraphsparameter{\currentparagraphs:\recurselevel}\c!distance\relax
+ \fi}%
+ \ifnum\scratchcounter>\zerocount
+ \divide\d_typo_paragraphs_auto\scratchcounter
+ \else
+ \d_typo_paragraphs_auto\zeropoint
+ \fi
+ \parindent\zeropoint
+ \c_typo_paragraphs_n\zerocount
+ \let\\=\typo_paragraphs_next % downward compatible
+ \dontleavehmode\hbox
+ \bgroup % (2)
+ \forgetall
+ \let\typo_paragraphs_start_cell\typo_paragraphs_start_cell_indeed
+ \let\typo_paragraphs_stop_cell \typo_paragraphs_stop_cell_indeed
+ \typo_paragraphs_start_cell_indeed}
+
+\unexpanded\def\stopparagraphs
+ {\stopparagraphscell
+ \egroup % (2)
+ \paragraphsparameter\c!after
+ \egroup} % (1)
+
+\unexpanded\def\nextparagraphs
+ {\stopparagraphscell
+ \startparagraphscell}
+
+\unexpanded\def\startparagraphscell
+ {\typo_paragraphs_start_cell}
+
+\def\typo_paragraphs_start_cell_indeed
+ {\removeunwantedspaces
+ \advance\c_typo_paragraphs_n\plusone
+ \ifnum\c_typo_paragraphs_n>\c_typo_paragraphs_max
+ \expandafter\typo_paragraphs_start_cell_nop
+ \else
+ \expandafter\typo_paragraphs_start_cell_yes
+ \fi}
+
+\def\typo_paragraphs_start_cell_nop
+ {\begingroup
+ % message: too many cells in paragraphs
+ \let\typo_paragraphs_start_cell\relax
+ \let\typo_paragraphs_stop_cell\typo_paragraphs_stop_cell_indeed
+ \setbox\scratchbox\vbox\bgroup}
+
+\def\typo_paragraphs_start_cell_yes
+ {\begingroup
+ \let\typo_paragraphs_start_cell\relax
+ \let\typo_paragraphs_stop_cell\typo_paragraphs_stop_cell_indeed
+ \edef\currentparagraphs{\currentparagraphs:\the\c_typo_paragraphs_n}%
+ \ifnum\c_typo_paragraphs_n>\plusone
+ \typo_paragraphs_separator
+ \fi
+ \edef\p_height{\paragraphsparameter\c!height}%
+ \edef\p_width {\paragraphsparameter\c!width }%
+ \useparagraphsstyleandcolor\c!style\c!color
+ \setbox\scratchbox\vtop \ifx\p_height\empty \else\ifx\p_height\v!fit \else to \p_height \fi\fi
+ \bgroup % (2)
+ \blank[\v!disable]%
+ \paragraphsparameter\c!top
+ \hsize\ifx\p_width\empty \d_typo_paragraphs_auto \else \p_width \fi \relax
+ \usealignparameter\paragraphsparameter
+ \paragraphsparameter\c!inner
+ \everypar{\begstrut\everypar\emptytoks}%
+ \ignorespaces
+ \paragraphsparameter\c!command}
+
+\unexpanded\def\stopparagraphscell
+ {\typo_paragraphs_stop_cell
+ \let\typo_paragraphs_stop_cell\relax}
+
+\def\typo_paragraphs_stop_cell_indeed
+ {\ifnum\c_typo_paragraphs_n>\c_typo_paragraphs_max
+ \expandafter\typo_paragraphs_stop_cell_nop
+ \else
+ \expandafter\typo_paragraphs_stop_cell_yes
+ \fi}
+
+\def\typo_paragraphs_stop_cell_nop
+ {\egroup
+ \endgroup}
+
+\def\typo_paragraphs_stop_cell_yes
+ {\ifvmode
+ \removelastskip
+ \else
+ \removeunwantedspaces
+ \endstrut
+ \endgraf
+ \fi
+ \paragraphsparameter\c!bottom
+ \egroup % (2)
+ \dontleavehmode\hbox{\raise\strutheight\box\scratchbox}%
+ \endgroup}
+
+\def\typo_paragraphs_separator
+ {\scratchdistance\paragraphsparameter\c!distance
+ \doif{\paragraphsparameter\c!rule}\v!on
+ {\scratchwidth\paragraphsparameter\c!rulethickness
+ \scratchdistance\dimexpr(\scratchdistance-\scratchwidth)/2\relax
+ \hskip\scratchdistance
+ \color[\paragraphsparameter\c!rulecolor]{\vrule\s!width\scratchwidth}}%
+ \hskip\scratchdistance}
+
+\protect \endinput
diff --git a/tex/context/base/tabl-ntb.mkiv b/tex/context/base/tabl-ntb.mkiv
index 99da4b5e8..9c7864184 100644
--- a/tex/context/base/tabl-ntb.mkiv
+++ b/tex/context/base/tabl-ntb.mkiv
@@ -1,5 +1,5 @@
%D \module
-%D [ file=core-ntb,
+%D [ file=tabl-ntb,
%D version=2000.04.18,
%D title=\CONTEXT\ Table Macros,
%D subtitle=Natural Tables,
@@ -11,16 +11,15 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This is an unfinished, preliminary module. At least two
-%D runs are needed to get the table fixed. Ugly code.
+%D This module as a more modern variant in xtables but as we follow a bit
+%D different approach with settings there, this mechanism will stay. In fact
+%D each of them has its advantages. This module could be sped up a bit and made
+%D more efficient by delegating some housekeeping to \LUA\ but it's not worth
+%D the effort. The code could me made more readable but again, there is no
+%D real purpose in it. If needed I can squeeze out a few more percentages
+%D runtime.
-% todo: TABLE TBL -> ntb
-% todo: special parsetb for argless variant
-% todo: protect \tbl...
-% todo: tblnx also count
-% todo: get rid of recurse
-% todo: fast if
-% todo: avoid halign (just do it manual) and thereby globals
+\writestatus{loading}{ConTeXt Table Macros / Natural Tables}
% bug: width 3cm is not honored and column becomes too wide
% as given width is added to distributed width
@@ -56,65 +55,14 @@
% \stopcelltable
% \stoptext
-% optie=rek beschrijven
-
-\writestatus{loading}{ConTeXt Table Macros / Natural Tables}
-
-%D As always, this is the nth version. Much time went in
+%D As always, this is the n\high{th} version. Much time went in
%D trying to speed up the many cell calculations, some
%D optimizations were rejected in order not to complicate this
-%D module too much (and in order to prevail extensibility).
+%D module too much (and in order to prevail extensibility). In the
+%D meantime we've sacrified some speed for readability.
-% shapebox fails here in mkii
-%
-% \setupcolors[state=start]
-% \bTABLE
-% \bTR [align=middle]\bTH Range\eTH{}\bTH Value\eTH{}\eTR
-% \bTR \bTD \type{<} 12\eTD{}\bTD 3\eTD{}\eTR
-% \bTR \bTD 12--16\eTD{}\bTD 2\eTD{}\eTR
-% \bTR \bTD \type{>}16\eTD{}\bTD 1\eTD{}\eTR
-% \eTABLE
-
-% \starttext
-% \placefigure[left]{}{}
-% \startlinecorrection \dontleavehmode \bTABLE
-% \bTR \bTD oeps \eTD \eTR
-% \eTABLE \stoplinecorrection
-% \placefigure[right]{}{}
-% \startlinecorrection \dontleavehmode \bTABLE
-% \bTR \bTD oeps \eTD \eTR
-% \eTABLE \stoplinecorrection
-% \stoptext
-
-%D To Do:
-%D
-%D \starttyping
-%D break over pagina
-%D kop herhalen
-%D reset settings
-%D
-%D \setupTABLE [c|column|x] [nx|odd|even|first|last][a=b]
-%D \setupTABLE [r|row |y] [nx|odd|even|first|last][a=b]
-%D \setupTABLE [nx|odd|even|first|last][ny|odd|even|first|last][a=b]
-%D \setupTABLE [nx|odd|even|first|last] [a=b]
-%D \setupTABLE [a=b]
-%D
-%D \bTH \eTH
-%D \stoptyping
-
-% the section setup does not work yet, data needs to be stored,
-% i.e.each row should know if it's a head/body/foot, and there
-% should be \setupTABLE[head]... and alike
-
\unprotect
-%D A simple way to force equal line spacing is to say:
-%D
-%D \starttyping
-%D \def\bTBLCELL{\begstrut}
-%D \def\eTBLCELL{\endstrut}
-%D \stoptyping
-%D
%D The next alternative also takes care of preceding and following
%D white space.
%D
@@ -126,22 +74,25 @@
%D
%D \typebuffer \getbuffer
-\ifdefined\dotagTABLEcell \else \let\dotagTABLEcell \relax \fi
-\ifdefined\dotagTABLEsignal \else \let\dotagTABLEsignal\relax \fi
+\ifdefined\dotagTABLEcell \else \let\dotagTABLEcell \relax \fi % todo: namespace
+\ifdefined\dotagTABLEsignal \else \let\dotagTABLEsignal\relax \fi % todo: namespace
+
+\let\tabl_tnb_next_level\relax
-\def\bTBLCELL % why not \doinhibitblank
+\unexpanded\def\tabl_tnb_cell_start
{\inhibitblank
\dotagTABLEcell
- \dousestyleparameter\tbltblstyle
- \everypar{\tbltblleft\delayedbegstrut}}
+% \tabl_tnb_next_level
+ \usenaturaltablelocalstyleandcolor\c!style\c!color
+ \everypar{\naturaltablelocalparameter\c!left\delayedbegstrut}}
-\def\eTBLCELL
+\unexpanded\def\tabl_tnb_cell_stop
{\ifhmode
\delayedendstrut
- \tbltblright
+ \naturaltablelocalparameter\c!right
\par % added 13/4/2006
\else
- % not sure yet:\tbltblright
+ % not sure yet:\naturaltablelocalparameter\c!right
\par
\ifdim\prevdepth<\zeropoint % =-1000pt ?
\vskip-\strutdp
@@ -150,92 +101,195 @@
\fi
\fi}
-\newcount\currenttbl
+\newcount\c_tabl_ntb_row
+\newcount\c_tabl_ntb_col
+\newcount\c_tabl_ntb_spn
-\def\@@tbl{tbl} \def\tblcell{1} \def\tblnone{2}
+\newcount\c_tabl_ntb_nx
+\newcount\c_tabl_ntb_ny
-\def\@@tblprefix{tbl:} \let\@@rawtblprefix\@@tblprefix
+\setnewconstant\c_tabl_ntb_cell \plusone
+\setnewconstant\c_tabl_ntb_none \plustwo
-%D This should be done more efficient: soon
+\newcount\c_tabl_ntb_current_row
+\newcount\c_tabl_ntb_current_col
+\newcount\c_tabl_ntb_current_row_one
+\newcount\c_tabl_ntb_current_col_one
+\newcount\c_tabl_ntb_current_row_two
+\newcount\c_tabl_ntb_current_col_two
+\newcount\c_tabl_ntb_current_row_three
+\newcount\c_tabl_ntb_current_col_three
+\newcount\c_tabl_ntb_current_row_four
+\newcount\c_tabl_ntb_current_col_four
-% \let as well as \expandafter\edef's
+\newcount\c_tabl_ntb_running_col
+\newcount\c_tabl_ntb_maximum_row
+\newcount\c_tabl_ntb_maximum_col
+\newcount\c_tabl_ntb_maximum_row_span
+\newcount\c_tabl_ntb_maximum_col_span
-\newcounter\TBLlevel
+\newtoks\t_tabl_ntb
+\newtoks\t_tabl_ntb_row
-\def\@@tblprefix{\@@tbl:\ifnum\TBLlevel>1 :\TBLlevel:\fi}
+\newconstant\c_tabl_tbl_pass
-% \def\tblsetprefix % not yet used, figure out when .. may interfere with setup
-% {\edef\@@tblprefix{\@@tbl:\ifnum\TBLlevel>1 :\TBLlevel:\fi}}
+\newtoks\t_tabl_ntb_head
+\newtoks\t_tabl_ntb_next
+\newtoks\t_tabl_ntb_body
+\newtoks\t_tabl_ntb_foot
-\def\settblnob#1{\expandafter\let\csname\@@tblprefix\number#1:b\endcsname\plusone}
-\def\gettblnob#1{\ifcsname\@@tblprefix\number#1:b\endcsname\plusone\else\zerocount\fi}
+\newcount\c_tabl_ntb_n_of_head_lines
+\newcount\c_tabl_ntb_n_of_next_lines
+\newcount\c_tabl_ntb_n_of_hdnx_lines
-\def\settbltag#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:s\endcsname}
-\def\settblcol#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:c\endcsname}
-\def\settblrow#1#2{\expandafter\edef\csname\@@tblprefix\number#1:\number#2:r\endcsname}
+\newdimen\d_tabl_ntb_height
+\newdimen\d_tabl_ntb_width
-\def\lettbltag#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:s\endcsname}
-\def\lettblcol#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:c\endcsname}
-\def\lettblrow#1#2{\expandafter\let\csname\@@tblprefix\number#1:\number#2:r\endcsname}
+\newtoks\everyTABLEpass % public
-\def\settblwd#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:wd\endcsname} % global !
-\def\settblht#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:ht\endcsname} % global !
-\def\lettblwd#1#2{\global\expandafter\let\csname\@@tblprefix\number#1:\number#2:wd\endcsname} % global !
-\def\lettblht#1#2{\global\expandafter\let\csname\@@tblprefix\number#1:\number#2:ht\endcsname} % global !
+\newcount\tablecellrows % public (needs checking)
+\newcount\tablecellcolumns % public (needs checking)
-\def\gettbltag#1#2{\csname\@@tblprefix\number#1:\number#2:s\endcsname}
-\def\gettblcol#1#2{\csname\@@tblprefix\number#1:\number#2:c\endcsname}
-\def\gettblrow#1#2{\csname\@@tblprefix\number#1:\number#2:r\endcsname}
+\newbox\b_tabl_ntb_final
-\def\gettblwd #1#2{\csname\@@tblprefix\number#1:\number#2:wd\endcsname}
-\def\gettblht #1#2{\csname\@@tblprefix\number#1:\number#2:ht\endcsname}
+%D We have already prepared the previous macros for nesting,
+%D so we only have to pop in the right ones:
-\def\settblwid#1{\expandafter\xdef\csname\@@tblprefix\number#1:w\endcsname} % {#2} global !
-\def\settblhei#1{\expandafter\xdef\csname\@@tblprefix\number#1:h\endcsname} % {#2} global !
-\def\settbldis#1{\expandafter\xdef\csname\@@tblprefix\number#1:d\endcsname} % {#2} global !
-\def\settblaut#1{\expandafter\xdef\csname\@@tblprefix\number#1:a\endcsname} % {#2} global !
+\newcount\c_tabl_level
-\def\lettblwid#1{\global\expandafter\let\csname\@@tblprefix\number#1:w\endcsname} % {#2} global !
-\def\lettblhei#1{\global\expandafter\let\csname\@@tblprefix\number#1:h\endcsname} % {#2} global !
-\def\lettbldis#1{\global\expandafter\let\csname\@@tblprefix\number#1:d\endcsname} % {#2} global !
-\def\lettblaut#1{\global\expandafter\let\csname\@@tblprefix\number#1:a\endcsname} % {#2} global !
+\unexpanded\def\tabl_ntb_table_push
+ {\ifnum\m_tabl_tbl_level>\plusone
+ \tabl_ntb_parameters_reset
+ % we need a proper count push/pop
+ \xdef\m_tabl_ntb_saved_row{\the\c_tabl_ntb_row}\globalpushmacro\m_tabl_ntb_saved_row
+ \xdef\m_tabl_ntb_saved_col{\the\c_tabl_ntb_col}\globalpushmacro\m_tabl_ntb_saved_col
+ \else
+ \global\intabletrue
+ \fi}
-\def\gettblwid#1{\ifcsname\@@tblprefix\number#1:w\endcsname\csname\@@tblprefix\number#1:w\endcsname\else\zeropoint\fi}
-\def\gettblhei#1{\ifcsname\@@tblprefix\number#1:h\endcsname\csname\@@tblprefix\number#1:h\endcsname\else\zeropoint\fi}
-\def\gettbldis#1{\ifcsname\@@tblprefix\number#1:d\endcsname\csname\@@tblprefix\number#1:d\endcsname\else\zeropoint\fi}
-\def\gettblaut#1{\csname \@@tblprefix\number#1:a\endcsname}
+\unexpanded\def\tabl_ntb_table_pop
+ {\ifnum\m_tabl_tbl_level>\plusone
+ \globalpopmacro\m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row
+ \globalpopmacro\m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col
+ \else
+ \global\intablefalse
+ \fi}
-\def\doiftbltag #1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi}
-\def\doifnottbltag #1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\gobbleoneargument \else\@EA\firstofoneargument \fi}
-\def\doifelsetbltag#1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\@EA\firstoftwoarguments\else\@EA\secondoftwoarguments\fi}
-\def\doiftblrow #1#2{\ifcsname\@@tblprefix\number#1:\number#2:r\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi}
-\def\doiftblcol #1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi}
-\def\doifnottblcol #1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\endcsname\@EA\gobbleoneargument \else\@EA\firstofoneargument \fi}
+\unexpanded\def\tabl_tnb_next_level
+ {\advance\c_tabl_level\plusone
+ \edef\m_tabl_tbl_level{\the\c_tabl_level}}
+
+\unexpanded\def\tabl_tnb_prev_level
+ {\advance\c_tabl_level\minusone
+ \edef\m_tabl_tbl_level{\the\c_tabl_level}}
+
+\tabl_tnb_next_level % go to level 1
+
+\installcorenamespace{naturaltable} % was tbl
+\installcorenamespace{naturaltablelocal} % was tbltbl
+
+\installdirectcommandhandler \??naturaltable {naturaltable} % \??naturaltable
+\installsimpleframedcommandhandler \??naturaltablelocal {naturaltablelocal} \??naturaltablelocal
+
+\installcorenamespace{naturaltablenob}
+\installcorenamespace{naturaltabletag}
+\installcorenamespace{naturaltablecol}
+\installcorenamespace{naturaltablerow}
+\installcorenamespace{naturaltablewd}
+\installcorenamespace{naturaltableht}
+\installcorenamespace{naturaltabledp}
+\installcorenamespace{naturaltablewid}
+\installcorenamespace{naturaltablehei}
+\installcorenamespace{naturaltabledis}
+\installcorenamespace{naturaltableaut}
+\installcorenamespace{naturaltabletxt}
+\installcorenamespace{naturaltablespn}
+\installcorenamespace{naturaltableref}
+\installcorenamespace{naturaltableset}
+\installcorenamespace{naturaltablecell}
+
+\def\tabl_ntb_set_nob#1{\expandafter\let\csname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone}
+\def\tabl_ntb_get_nob#1{\ifcsname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone\else\zerocount\fi}
+
+\def\tabl_ntb_set_tag#1#2{\expandafter\edef\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_col#1#2{\expandafter\edef\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_row#1#2{\expandafter\edef\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_let_tag#1#2{\expandafter\let\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_let_col#1#2{\expandafter\let\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_let_row#1#2{\expandafter\let\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_set_wd#1#2{\expandafter\xdef\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+\def\tabl_ntb_set_ht#1#2{\expandafter\xdef\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+
+\def\tabl_ntb_let_wd#1#2{\global\expandafter\let\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+\def\tabl_ntb_let_ht#1#2{\global\expandafter\let\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+
+\def\tabl_ntb_get_tag#1#2{\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_col#1#2{\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_row#1#2{\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_get_wd#1#2{\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_ht#1#2{\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+
+\def\tabl_ntb_set_wid#1{\expandafter\xdef\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_hei#1{\expandafter\xdef\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_dis#1{\expandafter\xdef\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_set_aut#1{\expandafter\xdef\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+
+\def\tabl_ntb_let_wid#1{\global\expandafter\let\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_hei#1{\global\expandafter\let\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_dis#1{\global\expandafter\let\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_aut#1{\global\expandafter\let\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+
+\def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
+\def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
+\def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\else\zeropoint\fi}
+\def\tabl_ntb_get_aut#1{\csname \??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname}
+
+\def\tabl_ntb_tag_pattern#1#2{\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2}
+\def\tabl_ntb_row_pattern#1#2{\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2}
+\def\tabl_ntb_col_pattern#1#2{\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2}
+
+\def\tabl_ntb_tag_doif #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_tag_doifnot #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi}
+\def\tabl_ntb_tag_doifelse#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+\def\tabl_ntb_row_doif #1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_col_doif #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\def\tabl_ntb_col_doifnot #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi}
+
+% not used
+%
+% \def\tabl_ntb_tag_state#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
+% \def\tabl_ntb_row_state#1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
+% \def\tabl_ntb_col_state#1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi}
-\def\tbltagstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:s\endcsname\zerocount\else\plusone\fi}
-\def\tblrowstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:r\endcsname\zerocount\else\plusone\fi}
-\def\tblcolstate#1#2{\ifcsname\@@tblprefix\number#1:\number#2:c\endcsname\zerocount\else\plusone\fi}
+\def\tabl_ntb_set_spn #1{\expandafter\let\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone}
+\def\tabl_ntb_spn_doifelse#1{\doifelse {\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname}\!!plusone}
-\def\settblspn #1{\expandafter\let\csname\@@tblprefix\number#1:s\endcsname \!!plusone}
-\def\doifelsetblspn#1{\doifelse {\csname\@@tblprefix\number#1:s\endcsname}\!!plusone}
-% \def\doifelsetblspn#1{\@EA\ifx\csname\@@tblprefix\number#1:s\endcsname\plusone\@EA\firstoftwoarguments\else\@EA\secondoftwoarguments\fi}
+\def\tabl_ntb_set_spn #1{\setvalue {\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}}
+\def\tabl_ntb_spn_doifelse#1{\doifelsevalue{\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}}
-\def\settblspn #1{\setvalue {\@@tblprefix\number#1:s}{1}}
-\def\doifelsetblspn#1{\doifelsevalue{\@@tblprefix\number#1:s}{1}}
+\def\tabl_ntb_let_ref#1#2{\expandafter\glet\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_set_ref#1#2{\expandafter\xdef\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname}
+\def\tabl_ntb_get_ref#1#2{\ifcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\fi}
-\long\def\settbltxt#1#2#3%
- {\long\@EA\def\csname\@@tblprefix\number#1:\number#2:t\@EA\endcsname\@EA{\@EA\def\@EA\TBLlevel\@EA{\TBLlevel}#3}}
+% keep for a while:
+%
+% \unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% nasty: we restore the level
+% {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\expandafter\endcsname\expandafter
+% {\expandafter\def\expandafter\m_tabl_tbl_level\expandafter{\m_tabl_tbl_level}\tabl_ntb_cell_process{#3}{#4}[#5]{#6}}}
-\def\gettbltxt#1#2%
- {\csname\@@tblprefix\number#1:\number#2:t\endcsname}
+\unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6%
+ {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname
+ {\tabl_ntb_cell_process{#3}{#4}[#5]{\tabl_tnb_next_level#6\tabl_tnb_prev_level}}}
-\newtoks\tbltoks
-\newtoks\tblrowtoks
+\def\tabl_ntb_get_txt#1#2%
+ {\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname}
-\let\pushTBLparameters\relax
-\let\popTBLparameters \relax
+% to be changed:
-\newif\ifsqueezeTBLspan \squeezeTBLspantrue % spans one column cell over multi column par cells
+\newif\ifsqueezeTBLspan \squeezeTBLspantrue % spans one column cell over multi column par cells
\newif\ifautosqueezeTBLspan \autosqueezeTBLspantrue % unless explicit widths are given
\newif\ifautoTBLspread \autoTBLspreadfalse
\newif\ifautoTBLhsize \autoTBLhsizetrue
@@ -249,78 +303,90 @@
\newif\iftraceTABLE \traceTABLEfalse
-\def\noftblheadlines{0}
-\def\noftblnextlines{0}
-\def\noftblhdnxlines{0}
-
-\long\def\handleTBLcell#1#2[#3]{}
+% so far
-\long\def\bTC#1\eTC{\bTD#1\eTD}
-\long\def\bTX#1\eTX{\bTD#1\eTD}
-\long\def\bTY#1\eTY{\bTR#1\eTR}
+\unexpanded\def\tabl_ntb_cell_process#1#2[#3]{}
-\let\getTABLEparameters\getparameters
+\unexpanded\def\bTC#1\eTC{\bTD#1\eTD} \let\eTC\relax
+\unexpanded\def\bTX#1\eTX{\bTD#1\eTD} \let\eTX\relax
+\unexpanded\def\bTY#1\eTY{\bTR#1\eTR} \let\eTY\relax
\unexpanded\def\setupTABLE
- {\dotripleempty\dosetupTABLE}
+ {\dotripleempty\tabl_ntb_setup}
-\def\dosetupTABLE[#1][#2][#3]%
+\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
+
+\def\tabl_ntb_setup
{\ifthirdargument
- \processaction
- [#1]
- [ \v!row=>{\dosetupTABLExy[\c!y][#2][#3]},%
- \v!column=>{\dosetupTABLExy[\c!x][#2][#3]},%
- r=>{\dosetupTABLExy[\c!y][#2][#3]},%
- c=>{\dosetupTABLExy[\c!x][#2][#3]},%
- y=>{\dosetupTABLExy[\c!y][#2][#3]},%
- x=>{\dosetupTABLExy[\c!x][#2][#3]},%
- \v!start=>{\dosetupTABLExy[#1][#2][#3]},%
- \v!header=>{\dosetupTABLExy[#1][#2][#3]},%
- \s!unknown=>{\dosetupTABLEzz[#1][#2][#3]}]%
+ \expandafter\tabl_ntb_setup_three
\else\ifsecondargument
- \processaction
- [#1]
- [ \v!row=>{\dosetupTABLExy[\c!y][\v!each][#2]},%
- \v!column=>{\dosetupTABLExy[\c!x][\v!each][#2]},%
- r=>{\dosetupTABLExy[\c!y][\v!each][#2]},%
- c=>{\dosetupTABLExy[\c!x][\v!each][#2]},%
- y=>{\dosetupTABLExy[\c!y][\v!each][#2]},%
- x=>{\dosetupTABLExy[\c!x][\v!each][#2]},%
- \v!start=>{\dosetupTABLExy[#1][\v!each][#2]},%
- \v!header=>{\dosetupTABLExy[#1][\v!each][#2]},%
- \s!unknown=>{\dosetupTABLEzz[\c!x][#1][#2]}]%
+ \doubleexpandafter\tabl_ntb_setup_two
\else
- \getparameters[\@@tbl\@@tbl][#1]%
+ \doubleexpandafter\tabl_ntb_setup_one
\fi\fi}
-\def\dosetupTABLExy[#1][#2][#3]%
- {\def\dodosetupTABLE##1{\setTABLEparameters[#1##1][#3]}%
- \processcommalist[#2]\dodosetupTABLE}
-
-\def\dosetupTABLEzz[#1][#2][#3]%
- {\def\dodosetupTABLE##1%
- {\def\dododosetupTABLE####1{\setTABLEparameters[\c!x##1\c!y####1][#3]}%
- \processcommalist[#2]\dododosetupTABLE}%
- \processcommalist[#1]\dodosetupTABLE}
-
-\def\nopTABLEparameters[#1][#2]%
- {\letvalueempty{\@@tblprefix#1}} % can be made faster
-
-\def\setTABLEparameters[#1][#2]%
- {\pushTBLparameters
- \ifappendTBLsetups
- \doifdefinedelse{\@@tblprefix#1}
- {\def\getTABLEparameters[##1][##2]%
- {\setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][##2,#2]}}%
- \getvalue{\@@tblprefix#1}%
- \let\getTABLEparameters\getparameters}
- {\setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][#2]}}%
+\def\tabl_ntb_setup_one[#1][#2][#3]%
+ {\setupcurrentnaturaltablelocal[#1]}
+
+\def\tabl_ntb_setup_xy[#1][#2][#3]%
+ {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set[#1##1][#3]}%
+ \processcommalist[#2]\tabl_ntb_setup_step}
+
+\def\tabl_ntb_setup_un[#1][#2][#3]%
+ {\def\tabl_ntb_setup_step##1%
+ {\def\tabl_ntb_setup_step_step####1{\tabl_ntb_parameters_set[\c!x##1\c!y####1][#3]}%
+ \processcommalist[#2]\tabl_ntb_setup_step_step}%
+ \processcommalist[#1]\tabl_ntb_setup_step}
+
+\def\tabl_ntb_setup_each[#1][#2][#3]% ignores #3
+ {\tabl_ntb_parameters_set[#1\v!each][#2]}
+
+\def\tabl_ntb_setup_ux[#1][#2][#3]% ignores #3
+ {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set[\c!x##1][#2]}%
+ \processcommalist[#1]\tabl_ntb_setup_step}
+
+\installcorenamespace{naturaltablesetupthree}
+\installcorenamespace{naturaltablesetuptwo}
+
+\def\tabl_ntb_setup_three[#1]{\csname\??naturaltablesetupthree\ifcsname\??naturaltablesetupthree#1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+\def\tabl_ntb_setup_two [#1]{\csname\??naturaltablesetuptwo \ifcsname\??naturaltablesetuptwo #1\endcsname#1\else\s!unknown\fi\endcsname[#1]}
+
+\setvalue{\??naturaltablesetupthree \v!row}[#1]{\tabl_ntb_setup_xy [\c!y]}
+\setvalue{\??naturaltablesetupthree \v!column}[#1]{\tabl_ntb_setup_xy [\c!x]}
+\setvalue{\??naturaltablesetupthree \v!start}[#1]{\tabl_ntb_setup_xy [\v!start]}
+\setvalue{\??naturaltablesetupthree \v!header}[#1]{\tabl_ntb_setup_xy [\v!header]}
+
+\setvalue{\??naturaltablesetuptwo \v!row}[#1]{\tabl_ntb_setup_each[\c!y]}
+\setvalue{\??naturaltablesetuptwo \v!column}[#1]{\tabl_ntb_setup_each[\c!x]}
+\setvalue{\??naturaltablesetuptwo \v!start}[#1]{\tabl_ntb_setup_each[\v!start]}
+\setvalue{\??naturaltablesetuptwo \v!header}[#1]{\tabl_ntb_setup_each[\v!header]}
+
+\letvalue{\??naturaltablesetupthree\s!unknown}\tabl_ntb_setup_un
+\letvalue{\??naturaltablesetuptwo \s!unknown}\tabl_ntb_setup_ux
+
+\letcsnamecsname\csname\??naturaltablesetupthree r\endcsname\csname\??naturaltablesetupthree \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree c\endcsname\csname\??naturaltablesetupthree\v!column\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree y\endcsname\csname\??naturaltablesetupthree \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetupthree x\endcsname\csname\??naturaltablesetupthree\v!column\endcsname
+
+\letcsnamecsname\csname\??naturaltablesetuptwo r\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo c\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo y\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname
+\letcsnamecsname\csname\??naturaltablesetuptwo x\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname
+
+\def\tabl_ntb_parameters_set[#1][#2]%
+ {\ifappendTBLsetups
+ \ifcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname
+ \def\tabl_ntb_parameters_get[##1]%
+ {\setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[##1,#2]}}%
+ \getvalue{\??naturaltableset\m_tabl_tbl_level:#1}%
+ \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
+ \else
+ \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}%
+ \fi
\else
- \setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][#2]}%
- \fi
- \popTBLparameters}
-
-\let\setupTBLsection\relax
+ \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}%
+ \fi}
% % \setupTABLE [y] [first][background=color,backgroundcolor=blue,frame=off,bottomframe=on,topframe=on,framecolor=white]
% \setupTABLE [first][first][backgroundcorner=2,corner=10,frame=on]
@@ -382,87 +448,91 @@
%D
%D \start \tightTBLrowspanfalse \getbuffer \stop
-\unexpanded\def\setupTBLcell#1#2% cell over col over row
- {\setupTBLsection % already forgotten
- \edef\positiverow{\number#1}%
- \edef\positivecol{\number#2}%
- \edef\negativerow{\the\numexpr-\maximumrow+#1+\minusone\relax}%
- \edef\negativecol{\the\numexpr-\maximumcol+#2+\minusone\relax}%
+\let\tabl_ntb_setup_section\relax
+
+\unexpanded\def\tabl_ntb_setup_cell#1#2% cell over col over row
+ {\tabl_ntb_setup_section % already forgotten
+ \edef\m_tabl_ntb_positive_row{\number#1}%
+ \edef\m_tabl_ntb_positive_col{\number#2}%
+ \edef\m_tabl_ntb_negative_row{\the\numexpr-\c_tabl_ntb_maximum_row+#1+\minusone\relax}%
+ \edef\m_tabl_ntb_negative_col{\the\numexpr-\c_tabl_ntb_maximum_col+#2+\minusone\relax}%
+ % saves tokens (no speed gain)
+ \edef\m_tabl_ntb_prefix{\??naturaltableset\m_tabl_tbl_level:}%
% each each
- \csname\@@tblprefix\c!x\v!each\c!y\v!each\endcsname
- \csname\@@tblprefix\c!y\v!each\endcsname
- \csname\@@tblprefix\c!x\v!each\endcsname
+ \csname\m_tabl_ntb_prefix\c!x\v!each\c!y\v!each\endcsname
+ \csname\m_tabl_ntb_prefix\c!y\v!each\endcsname
+ \csname\m_tabl_ntb_prefix\c!x\v!each\endcsname
% odd even
- \csname\@@tblprefix\c!y\v!oddeven\positiverow\endcsname
- \csname\@@tblprefix\c!x\v!oddeven\positivecol\endcsname
- \csname\@@tblprefix\c!x\v!oddeven\positivecol\c!y\v!oddeven\positiverow\endcsname
+ \csname\m_tabl_ntb_prefix\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
+ \csname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\endcsname
+ \csname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
% row/col number combinations
- \ifcsname\@@tblprefix\c!y\positiverow\endcsname\csname\@@tblprefix\c!y\positiverow\endcsname\fi
- \ifcsname\@@tblprefix\c!y\negativerow\endcsname\csname\@@tblprefix\c!y\negativerow\endcsname\fi
- \csname\@@tbl\@@tbl\c!extras\endcsname
- \@EA\let\csname\@@tbl\@@tbl\c!extras\endcsname\relax % new, see x-fo
- \ifcsname\@@tblprefix\c!x\positivecol\endcsname\csname\@@tblprefix\c!x\positivecol\endcsname\fi
- \ifcsname\@@tblprefix\c!x\negativecol\endcsname\csname\@@tblprefix\c!x\negativecol\endcsname\fi
- \csname\@@tbl\@@tbl\c!extras\endcsname
- \@EA\let\csname\@@tbl\@@tbl\c!extras\endcsname\relax % new, see x-fo
+ \ifcsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname\fi
+ \ifcsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname\csname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname\fi
+ \naturaltablelocalparameter\c!extras
+ \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
+ \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname\fi
+ \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname\fi
+ \naturaltablelocalparameter\c!extras
+ \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
% first/last combinations
- \ifnum\positiverow=\plusone
- \csname\@@tblprefix\c!y\v!first\endcsname
- \ifcsname\@@tblprefix\c!x\positivecol\c!y\v!first\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\v!first\endcsname\fi
+ \ifnum\m_tabl_ntb_positive_row=\plusone
+ \csname\m_tabl_ntb_prefix\c!y\v!first\endcsname
+ \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname\fi
\fi
- \ifnum\positivecol=\plusone
- \csname\@@tblprefix\c!x\v!first\endcsname
- \ifcsname\@@tblprefix\c!x\v!first\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\v!first\c!y\positiverow\endcsname\fi
+ \ifnum\m_tabl_ntb_positive_col=\plusone
+ \csname\m_tabl_ntb_prefix\c!x\v!first\endcsname
+ \ifcsname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname\fi
\fi
- \ifnum\positiverow=\maximumrow\relax
- \csname\@@tblprefix\c!y\v!last\endcsname
- \ifcsname\@@tblprefix\c!x\positivecol\c!y\v!last\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\v!last\endcsname\fi
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
+ \csname\m_tabl_ntb_prefix\c!y\v!last\endcsname
+ \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname\fi
\fi
- \ifnum\positivecol=\maximumcol\relax
- \csname\@@tblprefix\c!x\v!last\endcsname
- \ifcsname\@@tblprefix\c!x\v!last\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\v!last\c!y\positiverow\endcsname\fi
+ \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \csname\m_tabl_ntb_prefix\c!x\v!last\endcsname
+ \ifcsname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname\fi
\fi
- \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\maximumcol\relax
- \csname\@@tblprefix\c!x\v!last\c!y\v!last\endcsname
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!last\endcsname
\fi\fi
- \ifnum\positiverow=\plusone \ifnum\positivecol=\plusone
- \csname\@@tblprefix\c!x\v!first\c!y\v!first\endcsname
+ \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\plusone
+ \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!first\endcsname
\fi\fi
- \ifnum\positiverow=\plusone \ifnum\positivecol=\maximumcol\relax
- \csname\@@tblprefix\c!x\v!last\c!y\v!first\endcsname
+ \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!first\endcsname
\fi\fi
- \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\plusone
- \csname\@@tblprefix\c!x\v!first\c!y\v!last\endcsname
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
+ \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!last\endcsname
\fi\fi
% special case: two rows and last row : two&first and two&last (round corners)
- \ifnum\maximumrow=\plustwo\relax
- \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\plusone
- \csname\@@tblprefix\c!x\v!first\c!y\v!two\endcsname
+ \ifnum\c_tabl_ntb_maximum_row=\plustwo\relax
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
+ \csname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!two\endcsname
\fi\fi
- \ifnum\positiverow=\maximumrow\relax \ifnum\positivecol=\maximumcol\relax
- \csname\@@tblprefix\c!x\v!last\c!y\v!two\endcsname
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
+ \csname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!two\endcsname
\fi\fi
\fi
- \ifnum\gettblcol\positiverow\positivecol=\maximumcol\relax % top span over whole width
- \ifnum\positiverow=\plusone
- \csname\@@tblprefix\c!x\v!one\c!y\v!first\endcsname
+ \ifnum\tabl_ntb_get_col\m_tabl_ntb_positive_row\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax % top span over whole width
+ \ifnum\m_tabl_ntb_positive_row=\plusone
+ \csname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!first\endcsname
\fi
- \ifnum\positiverow=\maximumrow\relax
- \csname\@@tblprefix\c!x\v!one\c!y\v!last\endcsname
+ \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
+ \csname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!last\endcsname
\fi
\fi
% header things
- \ifnum#1>\noftblhdnxlines\else
- \ifcsname\@@tblprefix\v!header\v!each \endcsname\csname\@@tblprefix\v!header\v!each \endcsname\fi
- \ifcsname\@@tblprefix\v!header\positivecol\endcsname\csname\@@tblprefix\v!header\positivecol\endcsname\fi
+ \ifnum#1>\c_tabl_ntb_n_of_hdnx_lines\else
+ \ifcsname\m_tabl_ntb_prefix\v!header\v!each \endcsname\csname\m_tabl_ntb_prefix\v!header\v!each \endcsname\fi
+ \ifcsname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname\csname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname\fi
\fi
% explicit cells
- \ifcsname\@@tblprefix\c!x\positivecol\c!y\positiverow\endcsname\csname\@@tblprefix\c!x\positivecol\c!y\positiverow\endcsname\fi
- \ifcsname\@@tblprefix\c!x\negativecol\c!y\negativerow\endcsname\csname\@@tblprefix\c!x\negativecol\c!y\negativerow\endcsname\fi
+ \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname\fi
+ \ifcsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname\csname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname\fi
% local
- \ifcsname\@@tblprefix\c!y++\positiverow\endcsname\csname\@@tblprefix\c!y++\positiverow\endcsname\fi
+ \ifcsname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname\csname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname\fi
% done
- \global\letcscsname\@@tblsplitafter\csname\@@tbl\@@tbl\c!after\endcsname
+ \xdef\m_tabl_ntb_after_split{\naturaltablelocalparameter\c!after}% to be checked
\relax}
% we cannot use +n (checking on number/last/first would slow down too much)
@@ -478,7 +548,7 @@
% \dorecurse{10}{\bTR \dorecurse{6}{\bTD xxx \eTD} \eTR}
% \eTABLE
-\globallet\@@tblsplitafter\relax
+\let\m_tabl_ntb_after_split\relax
% split + page:
%
@@ -488,101 +558,152 @@
% \bTR \bTD left \eTD\bTD right \eTD\eTR
% \eTABLE
-% todo: protect counters
+\unexpanded\def\tabl_ntb_tr
+ {\c_tabl_ntb_running_col\zerocount
+ \advance\c_tabl_ntb_maximum_row\plusone
+ \iffirstargument
+ \expandafter\tabl_ntb_tr_yes
+ \else
+ \expandafter\gobbleoneoptional
+ \fi}
-\newcount\row \newcount\col
-\newcount\xrow \newcount\xcol
-\newcount\xxrow \newcount\xxcol
-\newcount\maximumrow \newcount\maximumcol \newcount\maximumrowspan
- \newcount\currentcol
-\newcount\tblspn
+\def\tabl_ntb_tr_yes[#1]%
+ {\setvalue{\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_maximum_row}{\setupcurrentnaturaltablelocal[#1]}}
-\def\settblref#1#2{\expandafter\xdef\csname\@@tblprefix\number#1:\number#2:x\endcsname}
-\def\gettblref#1#2{\ifcsname\@@tblprefix\number#1:\number#2:x\endcsname\csname\@@tblprefix\number#1:\number#2:x\endcsname\fi}
+\def\m_tabl_ntb_default_nr{\naturaltableparameter\c!nr}
+\def\m_tabl_ntb_default_nc{\naturaltableparameter\c!nc}
-\def\parseTR[#1]%
- {\currentcol\zerocount
- \advance\maximumrow\plusone
- \iffirstargument
- \setvalue{\@@tblprefix\c!y++\number\maximumrow}{\getparameters[\@@tbl\@@tbl][#1]}% maybe also in mkii
+\unexpanded\def\tabl_ntb_td
+ {\iffirstargument
+ \expandafter\tabl_ntb_td_yes
+ \else
+ \expandafter\tabl_ntb_td_nop
\fi}
-\long\def\parseTD[#1]#2\eTD
- {\def\tblny{\tblnr}%
- \def\tblnx{\tblnc}%
- \let\tblnc\plusone
- \let\tblnr\plusone
- \let\tbln\currentcol
- \let\tblm\empty
- \iffirstargument
- \getparameters[\@@tbl][#1]%
- \fi
- % goto first cell % NEW, n/m=cellnumber
- \edef\@@tblnindeed{\csname\@@tbl\c!n\endcsname}%
- \ifx\@@tblnindeed\empty
- \global\advance\tblspn\tblnx\relax
- \else\ifnum\@@tblnindeed=\currentcol\else
- \scratchcounter\numexpr\@@tblnindeed-\currentcol+\minusone-\tblspn\relax
- \ifnum\scratchcounter>\zerocount
- \normalexpanded{\noexpand\parseTD[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no]}\eTD
- \fi
- % can also be made faster
- \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1,\c!n=,\c!m=]%
+\def\tabl_ntb_td_yes[#1]#2\eTD
+ {\letnaturaltableparameter\c!ny \m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx \m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc \plusone
+ \letnaturaltableparameter\c!nr \plusone
+ \letnaturaltableparameter\c!n \c_tabl_ntb_running_col
+ \letnaturaltableparameter\c!m \empty
+ \letnaturaltableparameter\c!action\empty % not that important
+ \setupcurrentnaturaltable[#1]%
+ %
+ \c_tabl_ntb_nx\naturaltableparameter\c!nx\relax
+ \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax
+ % goto first cell n/m=cellnumber
+ \edef\m_tabl_ntb_n{\naturaltableparameter\c!n}%
+ \edef\m_tabl_ntb_m{\naturaltableparameter\c!m}%
+ %
+ \ifx\m_tabl_ntb_n\empty
+ \global\advance\c_tabl_ntb_spn\c_tabl_ntb_nx\relax
+ \else\ifnum\m_tabl_ntb_n=\c_tabl_ntb_running_col\else
+ \tabl_ntb_td_pass_n{#1}%
\fi\fi
- \edef\@@tblmindeed{\csname\@@tbl\c!m\endcsname}%
- \ifx\@@tblmindeed\empty \else
- \ifnum\@@tblmindeed=\currentcol \else
- \scratchcounter\numexpr\@@tblmindeed-\currentcol+\minusone-\tblspn\relax
- \dorecurse\scratchcounter{\normalexpanded{\noexpand\parseTD[\c!n=,\c!m=]}\eTD}%
- % can be sped up
- \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1,\c!n=,\c!m=]% kind of double, see prev
+ \ifx\m_tabl_ntb_m\empty \else
+ \ifnum\m_tabl_ntb_m=\c_tabl_ntb_running_col\else
+ \tabl_ntb_td_pass_m{#1}%
\fi
\fi
\doloop % skip over columns that result from earlier span
- {\advance\currentcol\plusone
- \doifnottbltag\maximumrow\currentcol\exitloop}%
- % == \def\next{\advance\currentcol\plusone\doiftbltag\maximumrow\currentcol\next}\next
+ {\advance\c_tabl_ntb_running_col\plusone
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else
+ \exitloop
+ \fi}%
% fill r*c cells and set span
- \ifnum\tblnx=\plusone
- \ifnum\tblny=\plusone
- \ifnum\currentcol>\maximumcol\relax
- \maximumcol\currentcol
+ \c_tabl_ntb_nx\naturaltableparameter\c!nx\relax
+ \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax
+ \ifnum\c_tabl_ntb_nx=\plusone
+ \ifnum\c_tabl_ntb_ny=\plusone
+ \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col
\fi
\else
- \presetTBLcell
+ \tabl_ntb_cell_preset
\fi
\else
- \presetTBLcell
+ \tabl_ntb_cell_preset
\fi
% set values
- \lettbltag\maximumrow\currentcol\tblcell
- \settblcol\maximumrow\currentcol{\number\tblnx}%
- \settblrow\maximumrow\currentcol{\number\tblny}%
+ \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_nx}%
+ \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_ny}%
% the action key will change!
- \settblref\maximumrow\currentcol{\ifcsname\@@tbl\c!action\endcsname\csname\@@tbl\c!action\endcsname\fi}%
+ \tabl_ntb_set_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\naturaltableparameter\c!action}%
% save text
- \edef\celltag{{\number\maximumrow}{\number\currentcol}}%
- \@EA\settbltxt\@EA\maximumrow\@EA\currentcol\@EA{\@EA\handleTBLcell\celltag[#1]{#2}}}
-
-\def\presetTBLcell
- {\row\maximumrow
- \col\currentcol
- \dorecurse\tblny
- {\col\currentcol
- \settblcol\row\col{\number\tblnx}%
- \ifnum\tblnx>\maximumrowspan\relax
- \maximumrowspan\tblnx
- \fi
- \dorecurse\tblnx
- {\lettbltag\row\col\tblnone
- \advance\col\plusone}%
- \advance\row\plusone}%
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}%
+ {#1}{#2}}
+
+\def\tabl_ntb_td_nop[#1]#2\eTD
+ {\global\advance\c_tabl_ntb_spn\plusone\relax
+ \doloop
+ {\advance\c_tabl_ntb_running_col\plusone
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else
+ \exitloop
+ \fi}%
+ \c_tabl_ntb_nx\plusone
+ \c_tabl_ntb_ny\plusone
+ \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col
+ \fi
+ \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_nx}%
+ \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_ny}%
+ \tabl_ntb_let_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\empty
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}%
+ {#1}{#2}}
+
+\def\tabl_ntb_td_pass_n#1%
+ {\scratchcounter\numexpr\m_tabl_ntb_n-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax
+ \ifnum\scratchcounter>\zerocount
+ \normalexpanded{\tabl_ntb_td[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no]}\eTD
+ \fi
+ \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc\plusone
+ \letnaturaltableparameter\c!nr\plusone
+ \setupcurrentnaturaltable[#1]%
+ \letnaturaltableparameter\c!n \empty
+ \letnaturaltableparameter\c!m \empty}
+
+\def\tabl_ntb_td_pass_m#1%
+ {\scratchcounter\numexpr\m_tabl_ntb_m-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax
+ \dorecurse\scratchcounter{\normalexpanded{\tabl_ntb_td[\c!n=,\c!m=]}\eTD}%
+ % can be sped up
+ \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr
+ \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc
+ \letnaturaltableparameter\c!nc\plusone
+ \letnaturaltableparameter\c!nr\plusone
+ \setupcurrentnaturaltable[#1]%
+ \letnaturaltableparameter\c!n \empty
+ \letnaturaltableparameter\c!m \empty}
+
+\def\tabl_ntb_cell_preset
+ {\c_tabl_ntb_current_row\c_tabl_ntb_maximum_row
+ \c_tabl_ntb_current_col\c_tabl_ntb_running_col
+ \dorecurse\c_tabl_ntb_ny\tabl_ntb_cell_preset_rows
% check max column
- \advance\col\minusone
- \ifnum\col>\maximumcol\relax
- \maximumcol\col
+ \advance\c_tabl_ntb_current_col\minusone
+ \ifnum\c_tabl_ntb_current_col>\c_tabl_ntb_maximum_col\relax
+ \c_tabl_ntb_maximum_col\c_tabl_ntb_current_col
\fi}
+\def\tabl_ntb_cell_preset_rows
+ {\c_tabl_ntb_current_col\c_tabl_ntb_running_col
+ \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_nx}%
+ \ifnum\c_tabl_ntb_nx>\c_tabl_ntb_maximum_row_span\relax
+ \c_tabl_ntb_maximum_row_span\c_tabl_ntb_nx
+ \fi
+ \dorecurse\c_tabl_ntb_nx\tabl_ntb_cell_preset_cells
+ \advance\c_tabl_ntb_current_row\plusone}
+
+\def\tabl_ntb_cell_preset_cells
+ {\tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none
+ \advance\c_tabl_ntb_current_col\plusone}
+
%D The usage of n and m:
%D
%D \startbuffer
@@ -617,13 +738,13 @@
%D \stopbuffer
%D
%D \typebuffer \getbuffer
-
-\long\def\parseTH[#1]#2\eTH
- {\parseTD[#1,\c!color=\tbltblheadcolor,\c!style=\tbltblheadstyle,\c!aligncharacter=\v!no]#2\eTD}
-\long\def\parseTN[#1]#2\eTN
- {\parseTD[#1]\digits#2\relax\eTD}
-
+\def\tabl_ntb_th[#1]#2\eTH
+ {\tabl_ntb_td[#1,\c!color=\naturaltablelocalparameter\c!headcolor,\c!style=\naturaltablelocalparameter\c!headstyle,\c!aligncharacter=\v!no]#2\eTD}
+
+\def\tabl_ntb_tn[#1]#2\eTN
+ {\tabl_ntb_td[#1]\digits#2\relax\eTD}
+
%D Vit Zyka needed the option to create a distance between columns, so I
%D added support for individual column distances.
%D
@@ -668,86 +789,94 @@
%D \stopbuffer
%D
%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
-
-\newtoks\TBLhead
-\newtoks\TBLnext
-\newtoks\TBLbody
-\newtoks\TBLfoot
% to be done: head <raw> foot, dus state var
-\unexpanded\def\bTABLEhead{\dosingleempty\doTABLEhead} \let\eTABLEhead\relax
-\unexpanded\def\bTABLEnext{\dosingleempty\doTABLEnext} \let\eTABLEnext\relax
-\unexpanded\def\bTABLEbody{\dosingleempty\doTABLEbody} \let\eTABLEbody\relax
-\unexpanded\def\bTABLEfoot{\dosingleempty\doTABLEfoot} \let\eTABLEfoot\relax
+\unexpanded\def\bTABLEhead{\dosingleempty\tabl_ntb_head} \let\eTABLEhead\relax
+\unexpanded\def\bTABLEnext{\dosingleempty\tabl_ntb_next} \let\eTABLEnext\relax
+\unexpanded\def\bTABLEbody{\dosingleempty\tabl_ntb_body} \let\eTABLEbody\relax
+\unexpanded\def\bTABLEfoot{\dosingleempty\tabl_ntb_foot} \let\eTABLEfoot\relax
-\long\def\doTABLEhead[#1]#2\eTABLEhead{\appendtoks\doTABLEsection[#1]{#2}\to\TBLhead}
-\long\def\doTABLEnext[#1]#2\eTABLEnext{\appendtoks\doTABLEsection[#1]{#2}\to\TBLnext}
-\long\def\doTABLEbody[#1]#2\eTABLEbody{\appendtoks\doTABLEsection[#1]{#2}\to\TBLbody}
-\long\def\doTABLEfoot[#1]#2\eTABLEfoot{\appendtoks\doTABLEsection[#1]{#2}\to\TBLfoot}
+\def\tabl_ntb_head[#1]#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head}
+\def\tabl_ntb_next[#1]#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next}
+\def\tabl_ntb_body[#1]#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body}
+\def\tabl_ntb_foot[#1]#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot}
-\long\def\doTABLEsection[#1]#2%
- {\unexpanded\def\setupTBLsection{\getparameters[\@@tbl\@@tbl][#1]}%
+\def\tabl_ntb_section[#1]#2% also used in tabl-nte
+ {\unexpanded\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}%
#2%
- \let\setupTBLsection\relax}
-
-\let\pushTBL\relax
-\let\popTBL \relax
-
-\newconstant\tblpass
+ \let\tabl_ntb_setup_section\relax}
-\def\presetallTABLEparameters% each odd|even level / can be sped up but only once per table
- {\executeifdefined{\@@rawtblprefix\v!start\v!each}\relax
- \executeifdefined{\@@rawtblprefix\v!start\v!oddeven\TBLlevel}\relax
- \executeifdefined{\@@rawtblprefix\v!start\number\TBLlevel}\relax}
+\def\tabl_ntb_preset_parameters% each odd|even level / can be sped up but only once per table
+ {\ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
+ \csname\??naturaltableset\m_tabl_tbl_level:\v!start\v!each\endcsname
+ \fi
+ \ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname % hm
+ \csname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname
+ \fi
+ \ifcsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname % hm
+ \csname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname
+ \fi}
\unexpanded\def\bTABLE
- {\dosingleempty\dobTABLE}
+ {\dosingleempty\tabl_ntb_table}
-\def\dobTABLE[#1]%
- {\pushTBL
+\def\tabl_ntb_table[#1]%
+ {\tabl_ntb_table_push
% box not here
\bgroup
- \TBLhead\emptytoks
- \TBLnext\emptytoks
- \TBLbody\emptytoks
- \TBLfoot\emptytoks
+ \t_tabl_ntb_head\emptytoks
+ \t_tabl_ntb_next\emptytoks
+ \t_tabl_ntb_body\emptytoks
+ \t_tabl_ntb_foot\emptytoks
\ifhmode\kern\zeropoint\fi % blocks \removeunwantedspaces: check this on icare handelingsschema
\resetcharacteralign % new
- \getparameters
- [\@@tbl\@@tbl]
- [\c!align={\v!right,\v!broad,\v!high},#1]%
- \ifx\tbltblsetups\empty\else
- \doprocesslocalsetups\tbltblsetups
- \fi
- \hsize\tbltbltextwidth
+ \setupcurrentnaturaltablelocal[\c!align={\v!right,\v!broad,\v!high},#1]%
+ \doifsomething{\naturaltablelocalparameter\c!setups}\doprocesslocalsetups{\naturaltablelocalparameter\c!setups}%
+ \doifelse{\naturaltablelocalparameter\c!textwidth}\v!local
+ {\hsize\availablehsize}
+ {\hsize\naturaltablelocalparameter\c!textwidth}%
\processaction
- [\tbltblsplit]
+ [\naturaltablelocalparameter\c!split]
[ \v!yes=>\enableTBLbreaktrue,
\v!repeat=>\enableTBLbreaktrue\multipleTBLheadstrue,
\v!auto=>\ifinsidesplitfloat\enableTBLbreaktrue\fi]
\processaction
- [\tbltblheader]
+ [\naturaltablelocalparameter\c!header]
[\v!repeat=>\multipleTBLheadstrue]%
- \presetallTABLEparameters
+ \tabl_ntb_preset_parameters
\processallactionsinset
- [\tbltbloption]
+ [\naturaltablelocalparameter\c!option]
[\v!stretch=>\autoTBLspreadtrue]%
- \linewidth\tbltblrulethickness % needs to be frozen
+ \linewidth\naturaltablelocalparameter\c!rulethickness % needs to be frozen
\dontcomplain
- \currentcol\zerocount
- \maximumrowspan\plusone
- \maximumcol\zerocount
- \maximumrow\zerocount
+ \c_tabl_ntb_running_col \zerocount
+ \c_tabl_ntb_maximum_col \zerocount
+ \c_tabl_ntb_maximum_row \zerocount
+ \c_tabl_ntb_maximum_row_span\plusone
+ \let\currentTABLErow \tabl_ntb_current_row
+ \let\currentTABLEcolumn\tabl_ntb_current_column
+ \let\nofTABLErows \tabl_ntb_n_of_rows
+ \let\nofTABLEcolumns \tabl_ntb_n_of_columns
\let\bTR\dobTR
\let\bTD\dobTD
\let\bTH\dobTH
\let\bTN\dobTN}
-\unexpanded\def\dobTR{\dosingleempty\parseTR}
-\unexpanded\def\dobTD{\dosingleempty\parseTD}
-\unexpanded\def\dobTH{\dosingleempty\parseTH}
-\unexpanded\def\dobTN{\dosingleempty\parseTN}
+\def\tabl_ntb_current_row {\m_tabl_ntb_positive_row}
+\def\tabl_ntb_current_column{\m_tabl_ntb_positive_col}
+\def\tabl_ntb_n_of_rows {\number\c_tabl_ntb_maximum_row}
+\def\tabl_ntb_n_of_columns {\number\c_tabl_ntb_maximum_col}
+
+\let\currentTABLErow \!!zerocount
+\let\currentTABLEcolumn\!!zerocount
+\let\nofTABLErows \!!zerocount
+\let\nofTABLEcolumns \!!zerocount
+
+\unexpanded\def\dobTR{\dosingleempty\tabl_ntb_tr} % also used in tabl-nte
+\unexpanded\def\dobTD{\dosingleempty\tabl_ntb_td} % also used in tabl-nte
+\unexpanded\def\dobTH{\dosingleempty\tabl_ntb_th} % also used in tabl-nte
+\unexpanded\def\dobTN{\dosingleempty\tabl_ntb_tn} % also used in tabl-nte
% permits \expanded{\bTD ... \eTD}
@@ -758,302 +887,348 @@
\unexpanded\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode
{% tricky and dirty order -)
- \doifsometokselse\TBLhead % slow, better a flag
- {\the\TBLhead
- \edef\noftblheadlines{\number\maximumrow}%
- \doifsometokselse\TBLnext
- {\the\TBLnext
- \edef\noftblnextlines{\number\numexpr\maximumrow-\noftblheadlines\relax}}%
- {\let\noftblnextlines\zerocount}% was 1
- \edef\noftblhdnxlines{\number\maximumrow}}
- {\let\noftblheadlines\zerocount % was 1
- \let\noftblnextlines\zerocount
- \let\noftblhdnxlines\zerocount}%
- \the\TBLbody
- \the\TBLfoot
+ \doifsometokselse\t_tabl_ntb_head % slow, better a flag
+ {\the\t_tabl_ntb_head
+ \c_tabl_ntb_n_of_head_lines\c_tabl_ntb_maximum_row\relax
+ \doifsometokselse\t_tabl_ntb_next
+ {\the\t_tabl_ntb_next
+ \c_tabl_ntb_n_of_next_lines\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_n_of_head_lines\relax}%
+ {\c_tabl_ntb_n_of_next_lines\zerocount}% was 1
+ \c_tabl_ntb_n_of_hdnx_lines\c_tabl_ntb_maximum_row}
+ {\c_tabl_ntb_n_of_head_lines\zerocount % was 1
+ \c_tabl_ntb_n_of_next_lines\zerocount
+ \c_tabl_ntb_n_of_hdnx_lines\zerocount}%
+ \the\t_tabl_ntb_body
+ \the\t_tabl_ntb_foot
\removeunwantedspaces % only if hmode
% finish cells
- \dorecurse\maximumrow
- {\row\recurselevel\relax
- \dorecurse\maximumcol
- {\col\recurselevel\relax
- \doifnottbltag\row\col
- {\xxcol\col
- \xxrow\row
- \xrow\row
- \doloop
- {\xcol\col
- \doloop
- {\doifelsetbltag\xrow\xcol \exitloop
- {\advance\xcol\plusone
- \ifnum\xcol>\maximumcol\relax \exitloop \fi}}%
- \doifelsetbltag\xrow\xcol \exitloop
- {\xxrow\xrow \xxcol\xcol \advance\xrow\plusone
- \ifnum\xrow>\maximumrow \exitloop \fi}}%
- \ifnum\xxrow>\maximumrow\xxrow\maximumrow\fi
- \ifnum\xxcol>\maximumcol\xxcol\maximumcol\fi
- \xxrow\numexpr\xxrow-\row+\plusone\relax
- \xxcol\numexpr\xxcol-\col+\plusone\relax
- \xrow\row
- \dorecurse\xxrow
- {\xcol\col \settblcol\xrow\xcol{\number\xxcol}%
- \dorecurse\xxcol
- {\lettbltag\xrow\xcol\tblnone \advance\xcol\plusone}%
- \advance\xrow\plusone}%
- \lettbltag\row\col\tblcell
- \settblcol\row\col{\the\xxcol}%
- \settblrow\row\col{\the\xxrow}%
- \ifautoTBLemptycell
- \edef\celltag{{\number\row}{\number\col}}%
- \@EA\settbltxt\@EA\row\@EA\col\@EA{\@EA\handleTBLcell\celltag[]{\strut}}%
- \fi}}}%
+ \tabl_ntb_loop_one
% to be sure
- \dorecurse\maximumrow
- {\row\recurselevel\relax
- \dorecurse\maximumcol
- {\col\recurselevel\relax
- \doiftblrow\row\col
- {\scratchcounter\numexpr\maximumrow-\row+\plusone\relax
- \ifnum\gettblrow\row\col>\scratchcounter
- \settblrow\row\col{\the\scratchcounter}%
- \fi}%
- \lettblht\row\col\zeropoint
- \lettblwd\row\col\zeropoint
- \doifnottblcol\row\col{\lettblcol\row\col\zerocount}%
- \doifnottbltag\row\col{\lettbltag\row\col\tblnone}}}%
+ \tabl_ntb_loop_two
% check and do
- \ifcase\maximumcol\else
+ \ifcase\c_tabl_ntb_maximum_col\else
\startTBLprocessing
- \begTBL
- \dorecurse\maximumrow
- {\bTBL
- \row\recurselevel\relax
- \dorecurse\maximumcol
- {\col\recurselevel\relax
- \normalexpanded{\noexpand\doTBL{\number\row}{\number\col}}}%
- \eTBL}%
+ \tabl_ntb_table_start
+ \dorecurse\c_tabl_ntb_maximum_row
+ {\tabl_ntb_row_start
+ \c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \normalexpanded{\tabl_ntb_cell{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}}%
+ \tabl_ntb_row_stop}%
\removeunwantedspaces % only if hmode
- \endTBL
+ \tabl_ntb_table_stop
\stopTBLprocessing
% wrong ! ! ! better to have an auto-offset-overlay
- % \ifnum\TBLlevel>1
+ % \ifnum\m_tabl_tbl_level>1
% \vskip-\strutdp
% \fi
\fi
% tracing
% \iftrue
% \blank \tttf
- % \dorecurse\maximumrow
- % {\row\recurselevel\relax
- % \dorecurse\maximumcol
- % {\col\recurselevel\relax
- % [r=\the\row,c=\the\col,h=\the\dimexpr\gettblht\row\col,w=\the\dimexpr\gettblwd\row\col]}%
+ % \dorecurse\c_tabl_ntb_maximum_row
+ % {\c_tabl_ntb_current_row\recurselevel\relax
+ % \dorecurse\c_tabl_ntb_maximum_col
+ % {\c_tabl_ntb_current_col\recurselevel\relax
+ % [r=\the\c_tabl_ntb_current_row,c=\the\c_tabl_ntb_current_col,h=\the\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col,w=\the\dimexpr\tabl_ntb_get_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col]}%
% \par}%
% \blank
% \fi
\egroup
- \popTBL}
+ \tabl_ntb_table_pop}
-\let\startTBLprocessing\relax
-\let\stopTBLprocessing \relax
+\def\tabl_ntb_loop_one
+ {\dorecurse\c_tabl_ntb_maximum_row{\tabl_ntb_loop_one_rows}}
-\newcount\prelocatedTBLrows % \prelocateTBLrows{1000} may speed up large tables
+\def\tabl_ntb_loop_one_rows
+ {\c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col\tabl_ntb_loop_one_cells}
-\def\bTBL{\tblrowtoks\emptytoks}
-\def\eTBL{\tbltoks\@EA\@EA\@EA{\@EA\the\@EA\tbltoks\@EA\begintblrow\the\tblrowtoks\endtblrow}}%
-
-\def\prelocateTBLerror
- {\writestatus\m!system{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \number\prelocatedTBLrows)}}
+\def\tabl_ntb_loop_one_cells
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_loop_one_cells_indeed
+ \fi}
-\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway
- {\dostepwiserecurse\prelocatedTBLrows{#1}\plusone{\expandafter\newtoks\csname tbl:\recurselevel\endcsname}%
- \def\bTBL
- {\ifnum\tblrow<\prelocatedTBLrows\relax
- \@EA\let\@EA\tblrowtoks\csname tbl:\the\tblrow\endcsname\tblrowtoks\emptytoks
+\def\tabl_ntb_loop_one_cells_indeed
+ {\c_tabl_ntb_current_col_two\c_tabl_ntb_current_col
+ \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row
+ \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row
+ \doloop
+ {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col
+ \doloop
+ {\ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname
+ \exitloop
+ \else
+ \advance\c_tabl_ntb_current_col_one\plusone
+ \ifnum\c_tabl_ntb_current_col_one>\c_tabl_ntb_maximum_col\relax
+ \exitloop
+ \fi
+ \fi}%
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname
+ \exitloop
\else
- \prelocateTBLerror
+ \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row_one
+ \c_tabl_ntb_current_col_two\c_tabl_ntb_current_col_one
+ \advance\c_tabl_ntb_current_row_one\plusone
+ \ifnum\c_tabl_ntb_current_row_one>\c_tabl_ntb_maximum_row
+ \exitloop
+ \fi
\fi}%
- \def\eTBL
- {\tbltoks\@EA\@EA\@EA{\@EA\the\@EA\tbltoks\@EA\begintblrow\@EA\the\csname tbl:\the\tblrow\endcsname\endtblrow}}%
- \global\prelocatedTBLrows#1\relax}
+ \ifnum\c_tabl_ntb_current_row_two>\c_tabl_ntb_maximum_row\c_tabl_ntb_current_row_two\c_tabl_ntb_maximum_row\fi
+ \ifnum\c_tabl_ntb_current_col_two>\c_tabl_ntb_maximum_col\c_tabl_ntb_current_col_two\c_tabl_ntb_maximum_col\fi
+ \c_tabl_ntb_current_row_two\numexpr\c_tabl_ntb_current_row_two-\c_tabl_ntb_current_row+\plusone\relax
+ \c_tabl_ntb_current_col_two\numexpr\c_tabl_ntb_current_col_two-\c_tabl_ntb_current_col+\plusone\relax
+ \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row
+ \dorecurse\c_tabl_ntb_current_row_two
+ {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col
+ \tabl_ntb_set_col\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one{\the\c_tabl_ntb_current_col_two}%
+ \dorecurse\c_tabl_ntb_current_col_two
+ {\tabl_ntb_let_tag\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\c_tabl_ntb_none
+ \advance\c_tabl_ntb_current_col_one\plusone}%
+ \advance\c_tabl_ntb_current_row_one\plusone}%
+ \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_cell
+ \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_col_two}%
+ \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row_two}%
+ \ifautoTBLemptycell
+ \normalexpanded
+ {\tabl_ntb_set_txt_process\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}%
+ {}{\strut}%
+ \fi}
+
+\def\tabl_ntb_loop_two
+ {\dorecurse\c_tabl_ntb_maximum_row\tabl_ntb_loop_two_rows}
+
+\def\tabl_ntb_loop_two_rows
+ {\c_tabl_ntb_current_row\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col\tabl_ntb_loop_two_cells}
+
+\def\tabl_ntb_loop_two_cells
+ {\c_tabl_ntb_current_col\recurselevel\relax
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname
+ \scratchcounter\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_current_row+\plusone\relax
+ \ifnum\tabl_ntb_get_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col>\scratchcounter
+ \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\scratchcounter}%
+ \fi
+ \fi
+ \tabl_ntb_let_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint
+ \tabl_ntb_let_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint
+ \ifcsname\tabl_ntb_col_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_let_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zerocount
+ \fi
+ \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
+ \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none
+ \fi}
+
+\let\startTBLprocessing\relax % public
+\let\stopTBLprocessing \relax % public
+
+\newcount\c_tabl_prelocated_rows % \prelocateTBLrows{1000} may speed up large tables
+
+\def\tabl_ntb_row_start{\t_tabl_ntb_row\emptytoks}
+\def\tabl_ntb_row_stop {\normalexpanded{\t_tabl_ntb{\the\t_tabl_ntb\noexpand\tabl_ntb_row_align_start\the\t_tabl_ntb_row\tabl_ntb_row_align_stop}}}
+
+\def\tabl_ntb_prelocate_error
+ {\writestatus\m!system{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}}
% \prelocateTBLrows{1000} % may speed up large tables
+\installcorenamespace{naturaltabletok}
+
+\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway
+ {\dostepwiserecurse\c_tabl_prelocated_rows{#1}\plusone{\expandafter\newtoks\csname\??naturaltabletok\recurselevel\endcsname}%
+ \def\tabl_ntb_row_start
+ {\ifnum\c_tabl_ntb_row<\c_tabl_prelocated_rows\relax
+ \expandafter\let\expandafter\t_tabl_ntb_row\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\t_tabl_ntb_row\emptytoks
+ \else
+ \tabl_ntb_prelocate_error
+ \fi}%
+ \def\tabl_ntb_row_stop
+ {\normalexpanded{\t_tabl_ntb{\the\t_tabl_ntb\noexpand\tabl_ntb_row_align_start\the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\tabl_ntb_row_align_stop}}}%
+ \global\c_tabl_prelocated_rows#1\relax}
+
% We use aligments to handle the empty (skipped) columns, so
% that we don't have to (re|)|calculate these.
-\def\skiptblcol
- {\global\advance\tblcol\plusone}
+\def\tabl_ntb_column_skip
+ {\global\advance\c_tabl_ntb_col\plusone}
-\def\nexttblcol
- {\global\advance\tblcol\plusone
- \kern\tbltblcolumndistance
- &}
+\def\tabl_ntb_column_next
+ {\global\advance\c_tabl_ntb_col\plusone
+ \kern\naturaltablelocalparameter\c!columndistance
+ \aligntab}
-\def\spantblcol
+\def\tabl_ntb_column_span
{\span}
-\newcount\tblrow
-\newcount\tblcol
+\let\m_tabl_ntb_saved_row\!!zerocount
+\let\m_tabl_ntb_saved_col\!!zerocount
-\let\savedtblrow\!!zerocount
-\let\savedtblcol\!!zerocount
+\def\tabl_ntb_row_align_start
+ {\noalign{\tabl_ntb_row_align_reset}%
+ \tabl_ntb_column_next
+ \kern\dimexpr\naturaltablelocalparameter\c!leftmargindistance-\naturaltablelocalparameter\c!columndistance\relax}
-\def\begintblrow
- {\noalign
- {\global\advance\tblrow\plusone
- \global\tblcol\zerocount
- \global\tblspn\zerocount}%
- % \iftrue
- % \bgroup\tbox{\tttf[\number\tblrow]}\egroup
- % \fi
- \nexttblcol
- \kern\dimexpr\tbltblleftmargindistance-\tbltblcolumndistance\relax}
+\unexpanded\def\tabl_ntb_row_align_reset
+ {\global\advance\c_tabl_ntb_row\plusone
+ \global\c_tabl_ntb_col\zerocount
+ \global\c_tabl_ntb_spn\zerocount}
-\def\endtblrow
- {\kern\dimexpr\tbltblrightmargindistance-\tbltblcolumndistance\relax
+\unexpanded\def\tabl_ntb_row_align_stop
+ {\kern\dimexpr\naturaltablelocalparameter\c!rightmargindistance-\naturaltablelocalparameter\c!columndistance\relax
\crcr
\noalign
{\nointerlineskip
- \ifnum\tblrow>\noftblheadlines
- \ifnum\gettblnob\tblrow=\zerocount
+ \ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines
+ \ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount
\allowbreak
\fi
\else
\allowbreak % else no proper head split off
\fi
\bgroup % protect local vars
- \@@tblsplitafter
+ \m_tabl_ntb_after_split
\egroup
\bgroup % protect local vars
- \scratchcounter\numexpr\tblrow+\plusone\relax
- \ifnum\scratchcounter>\noftblhdnxlines\relax
- \ifnum\scratchcounter<\maximumrow\relax
- \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}%
+ \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \ifnum\scratchcounter>\c_tabl_ntb_n_of_hdnx_lines\relax
+ \ifnum\scratchcounter<\c_tabl_ntb_maximum_row\relax
+ \doifsomething{\naturaltablelocalparameter\c!spaceinbetween}
+ {\blank[\naturaltablelocalparameter\c!spaceinbetween]}%
\fi
\fi
\egroup}}
-\def\begintbl
- {\global\tblspn\zerocount
- \global\tblcol\zerocount
- \global\tblrow\zerocount
- \global\advance\tblrow\minusone
+\def\tabl_ntb_flush_content
+ {\the\everyTABLEpass
+ \global\c_tabl_ntb_spn\zerocount
+ \global\c_tabl_ntb_col\zerocount
+ \global\c_tabl_ntb_row\zerocount
+ \global\advance\c_tabl_ntb_row\minusone
\tabskip\zeropoint
\dostarttagged\t!table\empty
\dostarttagged\t!tablerow\empty
\appendtoks\dostoptagged\dostarttagged\t!tablerow\empty\to\everycr
\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&&\ignorespaces##\unskip\cr} % one too many
-
-\def\endtbl
- {\dostoptagged
+ \registerparoptions
+ % watch out: tagging the cell happens at the outer level (faster)
+ \ignorespaces\alignmark\alignmark\unskip
+ \aligntab\aligntab
+ \ignorespaces\alignmark\alignmark\unskip
+ \cr % one too many
+ \the\t_tabl_ntb
+ \dostoptagged
\egroup
\dostoptagged}
-\setvalue{\tblnone TBL}#1#2%
- {\spanTBL{#1}{#2}}
-
-\setvalue{\tblcell TBL}#1#2%
- {\tblrowtoks\expandafter{\the\tblrowtoks\makeTBL #1 #2 }% space delimited -> less tokens
- \spanTBL{#1}{#2}}
-
-\def\spanTBL#1#2%
- {\scratchcounter\gettblcol{#1}{#2}\relax
+\setvalue{\??naturaltablecell\the\c_tabl_ntb_none}#1#2%
+ {\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
\ifnum\scratchcounter>\zerocount
- \advance\scratchcounter \minusone
- \dorecurse\scratchcounter{\tblrowtoks\expandafter{\the\tblrowtoks\spantblcol}}%
- \dorecurse\scratchcounter{\tblrowtoks\expandafter{\the\tblrowtoks\skiptblcol}}%
- \tblrowtoks\expandafter{\the\tblrowtoks\nexttblcol}%
+ \advance\scratchcounter\minusone
+ \ifnum\scratchcounter>\zerocount
+ \tabl_ntb_span
+ \fi
+ \t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_column_next}
\fi}
-\def\doTBL#1#2%
- {\csname\gettbltag{#1}{#2}TBL\endcsname{#1}{#2}}
+\setvalue{\??naturaltablecell\the\c_tabl_ntb_cell}#1#2%
+ {\t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_pass #1 #2 }% space delimited -> less tokens
+ \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
+ \ifnum\scratchcounter>\zerocount
+ \advance\scratchcounter\minusone
+ \ifnum\scratchcounter>\zerocount
+ \tabl_ntb_span
+ \fi
+ \t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_column_next}
+ \fi}
-\def\begTBL
- {\global\tblspn\zerocount
- \global\tblrow\zerocount
- \global\tblcol\zerocount
- \tblpass\zerocount
- \tbltoks\emptytoks}
+\def\tabl_ntb_span
+ {\dorecurse\scratchcounter{\t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_column_span}}%
+ \dorecurse\scratchcounter{\t_tabl_ntb_row\expandafter{\the\t_tabl_ntb_row\tabl_ntb_column_skip}}}
-\newtoks\everyTABLEpass
+\unexpanded\def\tabl_ntb_cell#1#2%
+ {\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}}
-\def\flushtbltoks
- {\the\everyTABLEpass
- \begintbl
- \the\tbltoks
- \endtbl}
+\unexpanded\def\tabl_ntb_table_start
+ {\global\c_tabl_ntb_spn\zerocount
+ \global\c_tabl_ntb_row\zerocount
+ \global\c_tabl_ntb_col\zerocount
+ \c_tabl_tbl_pass\zerocount
+ \t_tabl_ntb\emptytoks}
-\def\domakeTBLone#1 #2 %
- {\gettbltxt{#1}{#2}}%
+\def\tabl_ntb_pass_one#1 #2 %
+ {\tabl_ntb_get_txt{#1}{#2}}%
-\def\domakeTBLtwo#1 #2 % meer in cellD
- {\scratchdimen\zeropoint
- \scratchcounter\tblcol
- \!!counta\gettblcol{#1}{#2}\relax
+\def\tabl_ntb_pass_two#1 #2 % meer in cellD
+ {\d_tabl_ntb_width\zeropoint
+ \scratchcounter\c_tabl_ntb_col
+ \!!counta\tabl_ntb_get_col{#1}{#2}\relax
\dorecurse\!!counta
- {\advance\scratchdimen\dimexpr\gettblwid\scratchcounter+\tbltblcolumndistance\relax
- \ifnum\recurselevel<\!!counta \advance\scratchdimen \gettbldis\scratchcounter\fi
+ {\advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ +\naturaltablelocalparameter\c!columndistance
+ \ifnum\recurselevel<\!!counta
+ +\tabl_ntb_get_dis\scratchcounter
+ \fi
+ \relax
\advance\scratchcounter\plusone}%
- \edef\widthTBL{\the\dimexpr\scratchdimen-\tbltblcolumndistance\relax}%
- \setbox\scratchbox\hbox{\gettbltxt{#1}{#2}}%
- \settblht{#1}{#2}{\the\ht\scratchbox}%
- \settblwd{#1}{#2}{\the\wd\scratchbox}%
- \ifdim\ht\scratchbox>\gettblhei{#1}\relax
- \settblhei{#1}{\the\ht\scratchbox}%
+ \advance\d_tabl_ntb_width-\naturaltablelocalparameter\c!columndistance\relax
+ \setbox\scratchbox\hbox{\tabl_ntb_get_txt{#1}{#2}}%
+ \tabl_ntb_set_ht{#1}{#2}{\the\ht\scratchbox}%
+ \tabl_ntb_set_wd{#1}{#2}{\the\wd\scratchbox}%
+ \ifdim\ht\scratchbox>\tabl_ntb_get_hei{#1}\relax
+ \tabl_ntb_set_hei{#1}{\the\ht\scratchbox}%
\fi}%
-\newcount\tablecellrows
-\newcount\tablecellcolumns
-
-\def\domakeTBLthree#1 #2 %
+\def\tabl_ntb_pass_three#1 #2 %
{% height
\dostarttagged\t!tablecell\empty
- \!!counta \gettblcol{#1}{#2}\relax
- \!!countb \gettblrow{#1}{#2}\relax
- \!!heighta\gettblht {#1}{#2}\relax
+ \!!counta \tabl_ntb_get_col{#1}{#2}\relax
+ \!!countb \tabl_ntb_get_row{#1}{#2}\relax
+ \!!heighta\tabl_ntb_get_ht {#1}{#2}\relax
\tablecellcolumns\!!counta % used later so don't adapt these
\tablecellrows \!!countb % used later so don't adapt these
- \scratchdimen\zeropoint
- \ifnum\!!counta=\maximumcol\relax
+ \d_tabl_ntb_height\zeropoint
+ \ifnum\!!counta=\c_tabl_ntb_maximum_col\relax
% case: nc=maxcolumns
\else
\scratchcounter#1\relax
\dorecurse\!!countb
- {\advance\scratchdimen\gettblhei\scratchcounter
+ {\advance\d_tabl_ntb_height\tabl_ntb_get_hei\scratchcounter
\advance\scratchcounter\plusone}%
- \ifdim\scratchdimen<\!!heighta\relax
- \scratchdimen\!!heighta
+ \ifdim\d_tabl_ntb_height<\!!heighta\relax
+ \d_tabl_ntb_height\!!heighta
\fi
\fi
- \edef\heightTBL{\the\scratchdimen}%
% width
- \scratchdimen\zeropoint
- \scratchcounter\tblcol
+ \d_tabl_ntb_width\zeropoint
+ \scratchcounter\c_tabl_ntb_col
\dorecurse\!!counta
- {\advance\scratchdimen\dimexpr\gettblwid\scratchcounter+\tbltblcolumndistance\relax
- \ifnum\recurselevel<\!!counta \advance\scratchdimen \gettbldis\scratchcounter\fi
+ {\advance\d_tabl_ntb_width\dimexpr
+ \tabl_ntb_get_wid\scratchcounter
+ +\naturaltablelocalparameter\c!columndistance
+ \ifnum\recurselevel<\!!counta
+ +\tabl_ntb_get_dis\scratchcounter
+ \fi
+ \relax
\advance\scratchcounter\plusone}%
- \edef\widthTBL{\the\dimexpr\scratchdimen-\tbltblcolumndistance\relax}%
+ \advance\d_tabl_ntb_width-\naturaltablelocalparameter\c!columndistance\relax
% cell
\setbox\scratchbox\hbox attr \taggedattribute \attribute\taggedattribute \bgroup
\dotagTABLEsignal % maybe we need to add some packaging in this case
- \gettbltxt{#1}{#2}%
+ \tabl_ntb_get_txt{#1}{#2}%
\egroup
- \ifnum\!!counta=\maximumcol\relax
+ \ifnum\!!counta=\c_tabl_ntb_maximum_col\relax
% case: nc=maxcolumns
\else
- \scratchdimen\gettblhei{#1}%
+ \scratchdimen\tabl_ntb_get_hei{#1}%
\setbox\scratchbox\hbox
{\lower\ht\scratchbox\hbox{\raise\scratchdimen\box\scratchbox}}%
\ht\scratchbox\scratchdimen
\fi
\dp\scratchbox\zeropoint
- \edef\!!stringa{\gettblref{#1}{#2}}%
+ \edef\!!stringa{\tabl_ntb_get_ref{#1}{#2}}%
\ifx\!!stringa\empty
\box\scratchbox
\else
@@ -1061,108 +1236,103 @@
\fi
\dostoptagged} % right spot
-\def\inTBLcell#1#2% hm, do we need #1 #2 ? we use tblcol anyway
+\def\tabl_tnb_cell_finalize
{\doifnotinset\localwidth{\v!fit,\v!broad}% user set
- {\scratchdimen\gettblaut\tblcol\relax
+ {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
\ifdim\localwidth>\scratchdimen
- \settblaut\tblcol{\the\dimexpr\localwidth\relax}%
- \fi}}%
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\dimexpr\localwidth}%
+ \fi}}
-\def\endTBL
+\def\tabl_ntb_table_stop
{\setbox\scratchbox\hbox
- {\localframed
- [\@@tbl\@@tbl]
- [\c!frame=\v!off,\c!background=,\c!align=\v!no]
- {\strut}}%
- \edef\minimalcellheight{\the\ht\scratchbox}%
- \dorecurse\maximumcol
- {\lettblaut\recurselevel\zeropoint
+ {\setupcurrentnaturaltablelocal[\c!frame=\v!off,\c!background=,\c!align=\v!no]%
+ \inheritednaturaltablelocalframed{\strut}}%
+ \edef\minimalcellheight{\the\ht\scratchbox}% not used
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\tabl_ntb_let_aut\recurselevel\zeropoint
% new
- \xcol\recurselevel\relax
- \dorecurse\maximumrow
- {\lettblwd\recurselevel\xcol\zeropoint
- \lettblht\recurselevel\xcol\zeropoint}%
+ \c_tabl_ntb_current_col_one\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_row
+ {\tabl_ntb_let_wd\recurselevel\c_tabl_ntb_current_col_one\zeropoint
+ \tabl_ntb_let_ht\recurselevel\c_tabl_ntb_current_col_one\zeropoint}%
% till here
- \lettblwid\recurselevel\zeropoint
- \lettbldis\recurselevel\zeropoint}%
- \dorecurse\maximumrow
- {\lettblhei\recurselevel\maxdimen}%
- \tblpass\plusone
- \let\makeTBL\domakeTBLone
- \let\handleTBLcell\dohandleTBLcellA
- \setbox0\vbox{\settrialtypesetting \flushtbltoks}%
-% \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}%
- \lettbldis\maximumcol\zeropoint
+ \tabl_ntb_let_wid\recurselevel\zeropoint
+ \tabl_ntb_let_dis\recurselevel\zeropoint}%
+ \dorecurse\c_tabl_ntb_maximum_row
+ {\tabl_ntb_let_hei\recurselevel\maxdimen}%
+ \c_tabl_tbl_pass\plusone
+ \let\tabl_ntb_pass\tabl_ntb_pass_one
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_a
+ \setbox0\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \tabl_ntb_let_dis\c_tabl_ntb_maximum_col\zeropoint
\ifautoTBLspread
% experimental, stretch non fixed cells to \hsize
- \checktblwidthsone % trial run
- \checktblwidthstwo % real run
- \stretchtblwidths
- \let\handleTBLcell\dohandleTBLcellB
- \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}%
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
+ \tabl_ntb_stretch_widths
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
\else\ifdim\wd0>\hsize
\ifautoTBLhsize
- \checktblwidthsone % trial run
- \checktblwidthstwo % real run
- \let\handleTBLcell\dohandleTBLcellB
- \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}%
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
\fi
- \else\ifautoTBLrowspan\ifnum\maximumrowspan>1 % max ?
+ \else\ifautoTBLrowspan\ifnum\c_tabl_ntb_maximum_row_span>1 % max ?
% added jan 2002 because nx=* did no longer work
\edef\savedhsize{\the\hsize}%
\hsize\wd0\relax % new per 17/04/2006
- \checktblwidthsone % trial run
- \checktblwidthstwo % real run
+ \tabl_ntb_check_widths_one % trial run
+ \tabl_ntb_check_widths_two % real run
\hsize\savedhsize
%
- \let\handleTBLcell\dohandleTBLcellC
- \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}%
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_c
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
\fi\fi\fi\fi
- \let\handleTBLcell\dohandleTBLcellD
- \tblpass\plustwo
- \let\makeTBL\domakeTBLtwo
- \setbox\scratchbox\vbox{\settrialtypesetting \flushtbltoks}%
- \checktblheightsone
- \checktblheightstwo
- \let\handleTBLcell\dohandleTBLcellE
- \tblpass\plusthree
- \let\makeTBL\domakeTBLthree
- \ifnum\TBLlevel>\plusone
- \@EA\notsplittblbox
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_d
+ \c_tabl_tbl_pass\plustwo
+ \let\tabl_ntb_pass\tabl_ntb_pass_two
+ \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
+ \tabl_ntb_check_heights_one
+ \tabl_ntb_check_heights_two
+ \let\tabl_ntb_cell_process\tabl_ntb_cell_process_e
+ \c_tabl_tbl_pass\plusthree
+ \let\tabl_ntb_pass\tabl_ntb_pass_three
+ \ifnum\m_tabl_tbl_level>\plusone
+ \expandafter\tabl_tbl_split_nop
\else\ifenableTBLbreak
- \@EAEAEA\splittblbox
+ \doubleexpandafter\tabl_tbl_split_yes
\else
- \@EAEAEA\notsplittblbox
- \fi\fi{\flushtbltoks}}
+ \doubleexpandafter\tabl_tbl_split_nop
+ \fi\fi{\tabl_ntb_flush_content}}
-\def\stretchtblwidths % more variants, e.g. a max to \dimend
- {\ifcase\maximumcol\else % else division by zero
+\def\tabl_ntb_stretch_widths % more variants, e.g. a max to \dimend
+ {\ifcase\c_tabl_ntb_maximum_col\else % else division by zero
\!!dimend\zeropoint
\!!dimene\hsize
- \dorecurse\maximumcol
- {\advance\!!dimend\dimexpr\gettblwid\recurselevel+\tbltblcolumndistance\relax
- \advance\!!dimene-\gettbldis\recurselevel}%
- \advance\!!dimend\dimexpr-\tbltblcolumndistance+\tbltblleftmargindistance+\tbltblrightmargindistance\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\advance\!!dimend\dimexpr\tabl_ntb_get_wid\recurselevel+\naturaltablelocalparameter\c!columndistance\relax
+ \advance\!!dimene-\tabl_ntb_get_dis\recurselevel}%
+ \advance\!!dimend\dimexpr-\naturaltablelocalparameter\c!columndistance+\naturaltablelocalparameter\c!leftmargindistance+\naturaltablelocalparameter\c!rightmargindistance\relax
% distribute width (stretch)
\ifdim\!!dimend<\!!dimene
\advance\!!dimend-\!!dimene
\!!dimend-\!!dimend
- \divide\!!dimend\maximumcol
- \dorecurse\maximumcol
- {\settblwid\recurselevel{\the\dimexpr\gettblwid\recurselevel+\!!dimend\relax}}%
+ \divide\!!dimend\c_tabl_ntb_maximum_col
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\tabl_ntb_set_wid\recurselevel{\the\dimexpr\tabl_ntb_get_wid\recurselevel+\!!dimend\relax}}%
\fi
\fi}
-\newbox\finaltblbox
-
-\def\notsplittblbox#1%
- {\setbox\finaltblbox\vbox{#1}%
- \postprocessTABLEbox\finaltblbox
+\def\tabl_tbl_split_nop#1%
+ {\setbox\b_tabl_ntb_final\vbox{#1}%
+ \postprocessTABLEbox\b_tabl_ntb_final
\beforeTABLEbox
- \box\finaltblbox
+ \box\b_tabl_ntb_final
\afterTABLEbox}
-\def\splittblbox#1%
+\def\tabl_tbl_split_yes % #1
{\ifinsidesplitfloat
\donetrue
\else\ifinsidefloat
@@ -1171,33 +1341,33 @@
\donetrue
\fi\fi
\ifdone
- \executeifdefined{dosplittblbox\tbltblsplitmethod}\dosplittblbox{#1}%
+ \expandafter\tabl_ntb_split_box
\else
- \notsplittblbox{#1}%
+ \expandafter\tabl_tbl_split_nop
\fi}
\newbox\TABLEsplitbox % public, don't change
\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox
-\def\dosplittblbox#1%
+\def\tabl_ntb_split_box#1%
{\resettsplit
\def\tsplitminimumfreelines{2}%
- \def\tsplitminimumfreespace{\dimexpr\extratblsplitheight+\tbltblsplitoffset\relax}%
+ \def\tsplitminimumfreespace{\dimexpr\extratblsplitheight+\naturaltablelocalparameter\c!splitoffset\relax}%
\def\tsplitbeforeresult {\beforeTABLEsplitbox}%
\def\tsplitafterresult {\afterTABLEsplitbox}%
- \def\tsplitafter {\@@tblsplitafter}%
+ \def\tsplitafter {\m_tabl_ntb_after_split}%
\setbox\tsplitcontent\vbox{#1}%
\ifmultipleTBLheads
- \dorecurse\noftblheadlines
+ \dorecurse\c_tabl_ntb_n_of_head_lines
{\setbox\scratchbox\vsplit\tsplitcontent to \lineheight
\setbox\tsplithead\vbox{\unvcopy\tsplithead\unvcopy\scratchbox}}%
- \dorecurse\noftblnextlines
+ \dorecurse\c_tabl_ntb_n_of_next_lines
{\setbox\scratchbox\vsplit\tsplitcontent to \lineheight
\setbox\tsplitnext\vbox{\unvcopy\tsplitnext\unvcopy\scratchbox}}%
\fi
- \doifsomething\tbltblspaceinbetween
- {\def\tsplitinbetween{\blank[\tbltblspaceinbetween]}}%
+ \doifsomething{\naturaltablelocalparameter\c!spaceinbetween}
+ {\def\tsplitinbetween{\blank[\naturaltablelocalparameter\c!spaceinbetween]}}%
\def\postprocesstsplit{\postprocessTABLEsplitbox{\box\tsplitresult}}%
\handletsplit}
@@ -1211,22 +1381,22 @@
\let\beforeTABLEbox \relax
\let\afterTABLEbox \relax
-\def\checktblwidthsone{\dochecktblwidths0} % 0 = trial run
-\def\checktblwidthstwo{\dochecktblwidths1} % 1 = real run
+\def\tabl_ntb_check_widths_one{\tabl_ntb_check_widths_indeed0} % 0 = trial run
+\def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed1} % 1 = real run
-\def\dochecktblwidths#1%
- {\iftraceTABLE\showtblwids{B#1}\fi
+\def\tabl_ntb_check_widths_indeed#1%
+ {\iftraceTABLE\tabl_ntb_show_widths{B#1}\fi
\!!counta\zerocount
- \!!dimena\dimexpr\hsize-\tbltblleftmargindistance-\tbltblrightmargindistance-\tbltblcolumndistance\relax
- \dorecurse\maximumcol
- {\scratchdimen\gettblaut\recurselevel\relax
- \advance\!!dimena-\gettbldis\recurselevel\relax
+ \!!dimena\dimexpr\hsize-\naturaltablelocalparameter\c!leftmargindistance-\naturaltablelocalparameter\c!rightmargindistance-\naturaltablelocalparameter\c!columndistance\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\scratchdimen\tabl_ntb_get_aut\recurselevel\relax
+ \advance\!!dimena-\tabl_ntb_get_dis\recurselevel\relax
\ifdim\scratchdimen>\zeropoint\relax
\advance\!!dimena -\scratchdimen
\else
- \scratchdimen\gettblwid\recurselevel\relax
- \ifdim\scratchdimen>\tbltblmaxwidth\relax
- \ifcase#1\else\lettblwid\recurselevel\zeropoint\fi
+ \scratchdimen\tabl_ntb_get_wid\recurselevel\relax
+ \ifdim\scratchdimen>\naturaltablelocalparameter\c!maxwidth\relax
+ \ifcase#1\else\tabl_ntb_let_wid\recurselevel\zeropoint\fi
\advance\!!counta \plusone
\else
\ifdim\scratchdimen>\zeropoint\relax
@@ -1239,163 +1409,157 @@
\fi
\fi}%
\ifcase\!!counta \else \divide\!!dimena \!!counta \fi
- \dorecurse\maximumcol
- {\scratchdimen\gettblwid\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax
\ifcase#1\relax
\ifdim\scratchdimen<\!!dimena % take natural width
- \settblaut\recurselevel{\the\scratchdimen}%
+ \tabl_ntb_set_aut\recurselevel{\the\scratchdimen}%
\fi
\else
\ifdim\scratchdimen=\zeropoint % auto set width
- \settblwid\recurselevel{\the\!!dimena}%
+ \tabl_ntb_set_wid\recurselevel{\the\!!dimena}%
\fi
\fi}%
- \iftraceTABLE\showtblwids{E#1}\fi}
-
-\newcount\xrowTBL
-\newcount\xcolTBL
-\newcount\xxrowTBL
+ \iftraceTABLE\tabl_ntb_show_widths{E#1}\fi}
-% dikke arg naar recurse wegwerken
-
-\def\dochecktblheightsone
- {\!!countb\gettblrow\xrowTBL\xcolTBL\relax
+\def\tabl_ntb_check_heights_one_indeed
+ {\!!countb\tabl_ntb_get_row\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\relax
% check row span
\ifnum\!!countb>\plusone
% current height in row
- \dimen0=\gettblht\xrowTBL\xcolTBL
+ \dimen0=\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three
% find nearest height in row
\dimen2=\zeropoint
- \dorecurse\maximumcol
- {\ifnum\recurselevel=\xcolTBL\else
- \doiftblrow\xrowTBL\recurselevel
- {\!!countc=\gettblrow\xrowTBL\recurselevel\relax
- \ifnum\!!countc=\plusone
- \dimen4=\gettblht\xrowTBL\recurselevel\relax
- \ifdim\dimen2<\dimen4
- \dimen2=\dimen4
- \fi
- \fi}%
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\ifnum\recurselevel=\c_tabl_ntb_current_col_three\else
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\recurselevel\endcsname
+ \!!countc=\tabl_ntb_get_row\c_tabl_ntb_current_row_three\recurselevel\relax
+ \ifnum\!!countc=\plusone
+ \dimen4=\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\recurselevel\relax
+ \ifdim\dimen2<\dimen4
+ \dimen2=\dimen4
+ \fi
+ \fi
+ \fi
\fi}%
- \xxrowTBL\xrowTBL
+ \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three
% calculate cummulative height
\dimen4=\dimen2
- \!!countc\xrowTBL
+ \!!countc\c_tabl_ntb_current_row_three
\advance\!!countc\minusone
\dorecurse\!!countb
- {\ifnum\xxrowTBL=\xrowTBL\else
- \advance\dimen4 \gettblhei\xxrowTBL
+ {\ifnum\c_tabl_ntb_current_row_four=\c_tabl_ntb_current_row_three\else
+ \advance\dimen4 \tabl_ntb_get_hei\c_tabl_ntb_current_row_four
\fi
\ifnum\recurselevel=\!!countb\else
- \settblnob\!!countc
+ \tabl_ntb_set_nob\!!countc
\advance\!!countc\plusone
\fi
- \advance\xxrowTBL\plusone}%
+ \advance\c_tabl_ntb_current_row_four\plusone}%
% distribute overshoot equally
\ifdim\dimen2>\zeropoint % new: test on natural-003
\ifdim\dimen4<\dimen0
\advance\dimen0 -\dimen4
\divide\dimen0 \!!countb
- \xxrowTBL\xrowTBL
- \settblhei\xrowTBL{\the\dimen2}%
+ \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}%
\dorecurse\!!countb
- {\dorecurse\maximumcol
- {\ifnum\recurselevel=\xcolTBL\else
- \scratchdimen\dimexpr\gettblht\xxrowTBL\recurselevel+\dimen0\relax
- \settblht\xxrowTBL\recurselevel{\the\scratchdimen}%
- \ifdim\gettblhei\xxrowTBL<\scratchdimen
- \settblhei\xxrowTBL{\the\scratchdimen}%
+ {\dorecurse\c_tabl_ntb_maximum_col
+ {\ifnum\recurselevel=\c_tabl_ntb_current_col_three\else
+ \scratchdimen\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row_four\recurselevel+\dimen0\relax
+ \tabl_ntb_set_ht\c_tabl_ntb_current_row_four\recurselevel{\the\scratchdimen}%
+ \ifdim\tabl_ntb_get_hei\c_tabl_ntb_current_row_four<\scratchdimen
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_four{\the\scratchdimen}%
\fi
\fi}%
- \advance\xxrowTBL\plusone}%
+ \advance\c_tabl_ntb_current_row_four\plusone}%
\else\ifdim\dimen4>\dimen0
\iftightTBLrowspan
- \settblhei\xrowTBL{\the\dimen2}%
+ \tabl_ntb_set_hei\c_tabl_ntb_current_row_three{\the\dimen2}%
\fi
\fi\fi
\fi
\fi}
-\def\checktblheightsone
- {\dorecurse\maximumrow
- {\xrowTBL\recurselevel\relax
- \dorecurse\maximumcol
- {\xcolTBL\recurselevel\relax
- \doiftblrow\xrowTBL\xcolTBL\dochecktblheightsone}}}
-\def\checktblheightstwo
+\def\tabl_ntb_check_heights_one
+ {\dorecurse\c_tabl_ntb_maximum_row
+ {\c_tabl_ntb_current_row_three\recurselevel\relax
+ \dorecurse\c_tabl_ntb_maximum_col
+ {\c_tabl_ntb_current_col_three\recurselevel\relax
+ \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\endcsname
+ \tabl_ntb_check_heights_one_indeed
+ \fi}}}
+
+\def\tabl_ntb_check_heights_two
{}
-\def\showtblwids#1%
+\def\tabl_ntb_show_widths#1%
{\vbox
- {\forgetall\tttf[#1]\dorecurse\maximumcol
- {\scratchdimen\gettblwid\recurselevel\relax
+ {\forgetall\tttf[#1]\dorecurse\c_tabl_ntb_maximum_col
+ {\scratchdimen\tabl_ntb_get_wid\recurselevel\relax
[\recurselevel:\the\scratchdimen]}}}
-\def\TBLcharalign
- {\doifelse\tbltblaligncharacter\v!yes
- \doTBLcharalign\gobbleoneargument}
+\def\tabl_ntb_char_align
+ {\doifelse{\naturaltablelocalparameter\c!aligncharacter}\v!yes
+ \tabl_ntb_char_align_indeed\gobbleoneargument}
-\long\def\doTBLcharalign#1#2% column data
+\def\tabl_ntb_char_align_indeed#1#2% column data
{\edef\alignmentclass{#1}%
- \edef\alignmentcharacter{\tbltblalignmentcharacter}%
- \ifcase\tblpass\or
+ \edef\alignmentcharacter{\naturaltablelocalparameter\c!alignmentcharacter}%
+ \ifcase\c_tabl_tbl_pass\or
\setfirstpasscharacteralign\checkalignment{#2}% {\strut#2\unskip}%
\fi % force hsize, so always a second
\setsecondpasscharacteralign \checkalignment{#2}% {\strut#2\unskip}%
\ignorespaces}
-% new, needed for icare first col of 'doeltabel', experimental
-
-\long\def\dohandleTBLcellA#1#2[#3]#4% grouping added ! ! !
+\unexpanded\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! !
{\bgroup
- \setupTBLcell{#1}{#2}%
+ \tabl_ntb_setup_cell{#1}{#2}%
\setbox\scratchbox\hbox
- {\scratchdimen\tbltbldistance\relax
- \ifdim\scratchdimen>\gettbldis{#2}\relax
- \settbldis{#2}{\the\scratchdimen}%
+ {\scratchdimen\naturaltablelocalparameter\c!distance\relax
+ \ifdim\scratchdimen>\tabl_ntb_get_dis{#2}\relax
+ \tabl_ntb_set_dis{#2}{\the\scratchdimen}%
\fi
- \localframed
- [\@@tbl\@@tbl]
- [#3,\c!background=,\c!frame=\v!off]% 25% faster
- {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL\inTBLcell{#1}{#2}}}%
- \scratchdimen\gettblwid\tblcol\relax
+ \setupcurrentnaturaltablelocal[#3,\c!background=,\c!frame=\v!off]% 25% faster
+ \inheritednaturaltablelocalframed{\tabl_tnb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_tnb_cell_stop\tabl_tnb_cell_finalize}}%
+ \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
\ifdim\wd\scratchbox>\scratchdimen
\ifsqueezeTBLspan
\ifautosqueezeTBLspan
- \doifinsetelse\tbltblwidth{\v!fit,\v!fixed,\v!broad,\v!local}
+ \doifinsetelse{\naturaltablelocalparameter\c!width}{\v!fit,\v!fixed,\v!broad,\v!local}
\donetrue \donefalse
\else
\donetrue
\fi
\ifdone % brr, 0
- \ifnum\number\gettblcol{#1}{#2}>\plusone \settblspn\tblcol\fi
+ \ifnum\tabl_ntb_get_col{#1}{#2}>\plusone \tabl_ntb_set_spn\c_tabl_ntb_col\fi
\fi
\fi
- \doifelsetblspn\tblcol
+ \tabl_ntb_spn_doifelse\c_tabl_ntb_col
\donothing
- {\ifdim\gettblwid\tblcol<\wd\scratchbox
- \settblwid\tblcol{\the\wd\scratchbox}%
+ {\ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox
+ \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}%
\fi}% auto set
\fi
- \scratchcounter\numexpr\tblrow+\plusone\relax
- \scratchdimen\gettblhei\scratchcounter\relax
+ \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax
\ifdim\ht\scratchbox<\scratchdimen
- \settblhei\scratchcounter{\the\ht\scratchbox}% auto set
+ \tabl_ntb_set_hei\scratchcounter{\the\ht\scratchbox}% auto set
\fi
- \settblht{#1}{#2}{\the\ht\scratchbox}%
- \settblwd{#1}{#2}{\the\wd\scratchbox}%
+ \tabl_ntb_set_ht{#1}{#2}{\the\ht\scratchbox}%
+ \tabl_ntb_set_wd{#1}{#2}{\the\wd\scratchbox}%
\ifautoTBLcheckwidth
\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
+ \scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax % can be a figure or so
\ifdim\scratchdimen=\zeropoint
% side effect: when width is set to 0pt,
% we can force a span that fits the sum of spans widths
- \settblaut\tblcol{\the\scratchdimen}%
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\scratchdimen}%
\else\ifdim\wd\scratchbox>\scratchdimen
% unless span
- \settblaut\tblcol{\the\wd\scratchbox}%
+ \tabl_ntb_set_aut\c_tabl_ntb_col{\the\wd\scratchbox}%
% to be translated
\writestatus\m!TABLE
{no auto width in (\number#1,\number#2)\space\the\wd\scratchbox/\the\hsize}%
@@ -1404,155 +1568,102 @@
\fi
\fi
\setbox2\emptyhbox
- \wd2\wd\scratchbox \ht2\ht\scratchbox \dp2\dp\scratchbox
+ \wd2\wd\scratchbox
+ \ht2\ht\scratchbox
+ \dp2\dp\scratchbox
\box2
\egroup}
-\long\def\dohandleTBLcellBC#1#2#3[#4]#5%
+\unexpanded\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5%
{\setbox\scratchbox\hbox
- {\setupTBLcell{#2}{#3}%
- \localframed
- [\@@tbl\@@tbl]
- [#4,#1,\c!frame=\v!off,\c!background=]
- {\bTBLCELL#5\eTBLCELL}}%
+ {\tabl_ntb_setup_cell{#2}{#3}%
+ \setupcurrentnaturaltablelocal[#4,#1,\c!frame=\v!off,\c!background=]%
+ \inheritednaturaltablelocalframed{\tabl_tnb_cell_start#5\tabl_tnb_cell_stop}}%
\setbox2\emptyhbox
- \wd2\wd\scratchbox \ht2\ht\scratchbox \dp2\dp\scratchbox
+ \wd2\wd\scratchbox
+ \ht2\ht\scratchbox
+ \dp2\dp\scratchbox
\ifautoTBLrowspan
- \scratchcounter\numexpr\tblrow+\plusone\relax
- \doiftblrow\scratchcounter\tblcol
- {\scratchdimen\gettblhei\scratchcounter\relax % moved inside test
- \ifnum\gettblrow\scratchcounter\tblcol>\plusone \ifdim\ht\scratchbox>\scratchdimen
- \scratchdimen-\scratchdimen \advance\scratchdimen -\ht\scratchbox
- \ht2\scratchdimen
- \fi \fi}%
+ \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax
+ \ifcsname\tabl_ntb_row_pattern\scratchcounter\c_tabl_ntb_col\endcsname
+ \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax
+ \ifnum\tabl_ntb_get_row\scratchcounter\c_tabl_ntb_col>\plusone
+ \ifdim\ht\scratchbox>\scratchdimen
+ \ht2\dimexpr-\scratchdimen-\ht\scratchbox\relax
+ \fi
+ \fi
+ \fi
\fi
\box2 }
-\long\def\dohandleTBLcellB#1#2[#3]#4%
- {\scratchdimen\gettblaut\tblcol\relax
+\unexpanded\def\tabl_ntb_cell_process_b#1#2[#3]#4%
+ {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
\ifdim\scratchdimen>\zeropoint\relax
- \let\tblwidthkey\c!width
- \edef\tblwidth{\the\scratchdimen}%
\else
- \scratchdimen\gettblwid\tblcol\relax
+ \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
\ifdim\scratchdimen>\zeropoint\relax
- \ifnum\gettblcol{#1}{#2}=\maximumcol\relax
+ \ifnum\tabl_ntb_get_col{#1}{#2}=\c_tabl_ntb_maximum_col\relax
\scratchdimen\hsize
\fi
- \let\tblwidthkey\c!width
- \edef\tblwidth{\the\scratchdimen}%
- \else
- \let\tblwidthkey\s!unknown
- \let\tblwidth\zeropoint
\fi
\fi
- \dohandleTBLcellBC{\tblwidthkey=\tblwidth}{#1}{#2}[#3]{\TBLcharalign{#2}{#4}}}
+ \normalexpanded{\tabl_ntb_cell_process_b_c{\ifdim\scratchdimen>\zeropoint \c!width=\the\scratchdimen\fi}}%
+ {#1}{#2}[#3]{\tabl_ntb_char_align{#2}{#4}}}
-\long\def\dohandleTBLcellC
- {\dohandleTBLcellBC{}}
+\unexpanded\def\tabl_ntb_cell_process_c
+ {\tabl_ntb_cell_process_b_c{}}
-\long\def\dohandleTBLcellD#1#2[#3]#4%
- {\setupTBLcell{#1}{#2}%
+\unexpanded\def\tabl_ntb_cell_process_d#1#2[#3]#4%
+ {\tabl_ntb_setup_cell{#1}{#2}%
\bgroup
- \localframed
- [\@@tbl\@@tbl]
- [#3,\c!width=\widthTBL,\c!background=,\c!frame=\v!off]% 25% faster
- {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}%
+ \setupcurrentnaturaltablelocal[#3,\c!width=\d_tabl_ntb_width,\c!background=,\c!frame=\v!off]% 25% faster
+ \inheritednaturaltablelocalframed{\tabl_tnb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_tnb_cell_stop}%
\egroup}
-\long\def\dohandleTBLcellE#1#2[#3]#4%
- {\setupTBLcell{#1}{#2}%
- \getparameters[\@@tbl\@@tbl][#3]% to get the color right, the way we
+\unexpanded\def\tabl_ntb_cell_process_e#1#2[#3]#4%
+ {\tabl_ntb_setup_cell{#1}{#2}%
+ \setupcurrentnaturaltablelocal[#3]% to get the color right, the way we
\color % handle color here prevents interference due to whatsit nodes
- [\tbltblcolor] % as well as permits local colors to take precedence
- {\ifdim\heightTBL=\zeropoint\relax % case: nc=maxcolumns
- \localframed
- [\@@tbl\@@tbl]
- [\c!color=,\c!width=\widthTBL]
- {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}%
+ [\naturaltablelocalparameter\c!color] % as well as permits local colors to take precedence
+ {\ifdim\d_tabl_ntb_height=\zeropoint\relax % case: nc=maxcolumns
+ \setupcurrentnaturaltablelocal[\c!color=,\c!width=\d_tabl_ntb_width]%
\else
- \localframed
- [\@@tbl\@@tbl]
- [\c!color=,\c!width=\widthTBL,\c!height=\heightTBL]
- {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}%
- \fi}%
- \hskip\gettbldis{#2}}
-
-\presetlocalframed % todo: tableparameter etc
- [\@@tbl\@@tbl]
-
-\setupTABLE [%
- \c!frameoffset=.5\linewidth,
- \c!backgroundoffset=\v!frame,
- \c!framecolor=\s!black,
- \c!width=\v!fit,
- \c!height=\v!fit,
- \c!autowidth=\v!yes,
- \c!rulethickness=\linewidth,
- \c!strut=\v!yes,
- \c!autostrut=\v!no,
- %
- \c!color=,
- \c!style=,
- \c!headstyle=\v!bold,
- \c!headcolor=,
- \c!aligncharacter=\v!no,
- \c!alignmentcharacter={,},
- \c!option=, % \v!stretch
- \c!header=,
- \c!spaceinbetween=,
- \c!maxwidth=8em,
- \c!textwidth=\hsize,
- \c!split=\v!auto,
- \c!splitoffset=0pt,
- \c!distance=\zeropoint, % individual column
- \c!columndistance=\zeropoint, % each column (whole table)
- \c!leftmargindistance=\zeropoint, % whole table
- \c!rightmargindistance=\zeropoint,% whole table
- \c!left=,
- \c!right=,
- \c!setups=,
- \c!splitmethod=a%
-]
-
-%D We have already prepared the previous macros for nesting,
-%D so we only have to pop in the right ones:
-
-%D New:
-
-\def\pushTBLparameters
- {\globalpushmacro\TBLlevel
- \ifcase\tblpass
- % we're just after \bTABLE
- \else\ifnum\TBLlevel>\zerocount
- \doglobal\increment\TBLlevel\relax
- \fi\fi}
-
-\def\popTBLparameters
- {\globalpopmacro\TBLlevel}
-
-\def\pushTBL
- {\ifnum\TBLlevel=\zerocount
- \global\advance\currenttbl\plusone
- \fi
- \doglobal\increment\TBLlevel\relax
- \ifnum\TBLlevel>\plusone
- \resetallTABLEparameters
- % we need a proper count push/pop
- \xdef\savedtblrow{\the\tblrow}\globalpushmacro\savedtblrow
- \xdef\savedtblcol{\the\tblcol}\globalpushmacro\savedtblcol
- \else
- \global\intabletrue
- \fi}
-
-\def\popTBL
- {\ifnum\TBLlevel>\plusone
- \globalpopmacro\savedtblrow\global\tblrow\savedtblrow
- \globalpopmacro\savedtblcol\global\tblcol\savedtblcol
- \else
- \global\intablefalse
- \fi
- \doglobal\decrement\TBLlevel\relax}
+ \setupcurrentnaturaltablelocal[\c!color=,\c!width=\d_tabl_ntb_width,\c!height=\d_tabl_ntb_height]%
+ \fi
+ \inheritednaturaltablelocalframed{\tabl_tnb_cell_start\tabl_ntb_char_align{#2}{#4}\tabl_tnb_cell_stop}}%
+ \hskip\tabl_ntb_get_dis{#2}}
+
+\setupTABLE
+ [\c!frameoffset=.5\linewidth,
+ \c!backgroundoffset=\v!frame,
+ \c!framecolor=\s!black,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!autowidth=\v!yes,
+ \c!rulethickness=\linewidth,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!no,
+ %
+ \c!color=,
+ \c!style=,
+ \c!headstyle=\v!bold,
+ \c!headcolor=,
+ \c!aligncharacter=\v!no,
+ \c!alignmentcharacter={,},
+ \c!option=, % \v!stretch
+ \c!header=,
+ \c!spaceinbetween=,
+ \c!maxwidth=8\emwidth,
+ \c!textwidth=\v!local, % was \hsize
+ \c!split=\v!auto,
+ \c!splitoffset=\zeropoint,
+ \c!distance=\zeropoint, % individual column
+ \c!columndistance=\zeropoint, % each column (whole table)
+ \c!leftmargindistance=\zeropoint, % whole table
+ \c!rightmargindistance=\zeropoint,% whole table
+ \c!left=,
+ \c!right=,
+ \c!setups=]
% \bgroup
% \setupTABLE[column][1][aligncharacter=yes, alignmentcharacter={,}]
@@ -1570,23 +1681,21 @@
\newconditional\resetTABLEmode \settrue\resetTABLEmode
-\def\resetallTABLEparameters% moet genest wel werken
- {\ifnum\TBLlevel>\plusone % in ieder geval
+\def\tabl_ntb_parameters_reset
+ {\ifnum\m_tabl_tbl_level>\plusone % in ieder geval
\ifconditional\resetTABLEmode
-% \presetlocalframed % breedte hoogte diepte offset
-% [\@@tbl\@@tbl]% % achtergrond, achtergrondraster, achtergrondkleur
% not ok yet
- \setupTABLE [%
- \c!frameoffset=.5\linewidth,
+ \setupTABLE
+ [\c!frameoffset=.5\linewidth,
\c!backgroundoffset=\v!frame,
\c!framecolor=\s!black,
\c!width=fit,
\c!height=fit,
-\c!autowidth=\v!yes,
-% \c!rulethickness=\linewidth,
+ \c!autowidth=\v!yes,
+ % \c!rulethickness=\linewidth,
\c!strut=\v!no,
-\c!strut=\v!yes, % needed for mathml, but ... maybe we need another resetTABLEmode
-\c!autostrut=\v!no,
+ \c!strut=\v!yes, % needed for mathml, but ... maybe we need another resetTABLEmode
+ \c!autostrut=\v!no,
\c!color=,
\c!style=,
\c!headstyle=,
@@ -1611,21 +1720,22 @@
% \bTRs[xx] \bTD oeps \eTD \bTD oeps \eTD \eTRs
% \eTABLE
+\installcorenamespace{naturaltablesetup}
+
\unexpanded\def\defineTABLEsetup
- {\dodoubleargument\dodefineTABLEsetup}
+ {\dodoubleargument\tabl_ntb_define_setup}
+
+\def\tabl_ntb_define_setup[#1][#2]%
+ {\setvalue{\??naturaltablesetup#1}{#2}}
-\def\dodefineTABLEsetup[#1][#2]%
- {\setvalue{\@@tbl:set:#1}{#2}}
+\let\eTDs\relax
+\let\eTRs\relax
-\long\def\bTDs[#1]#2\eTDs
- {\doifdefinedelse{\@@tbl:set:#1}
- {\@EA\@EA\@EA\bTD\@EA\@EA\@EA[\csname\@@tbl:set:#1\endcsname]#2\eTD}
- {\bTD[]#2\eTD}}
+\unexpanded\def\bTDs[#1]#2\eTDs
+ {\normalexpanded{\bTD[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTD}
-\long\def\bTRs[#1]#2\eTRs
- {\doifdefinedelse{\@@tbl:set:#1}
- {\@EA\@EA\@EA\bTR\@EA\@EA\@EA[\csname\@@tbl:set:#1\endcsname]#2\eTR}
- {\bTR[]#2\eTR}}
+\unexpanded\def\bTRs[#1]#2\eTRs
+ {\normalexpanded{\bTR[\ifcsname\??naturaltablesetup#1\endcsname\csname\??naturaltablesetup#1\endcsname\fi]}#2\eTR}
\protect \endinput
diff --git a/tex/context/base/tabl-nte.mkiv b/tex/context/base/tabl-nte.mkiv
index 08ab34f0f..4a9774cb0 100644
--- a/tex/context/base/tabl-nte.mkiv
+++ b/tex/context/base/tabl-nte.mkiv
@@ -28,7 +28,7 @@
%D
%D Let us start with the original macros:
%D
-%D \starttyping
+%D \startbuffer
%D \bTABLE
%D \bTR
%D \bTD Text 1 \eTD
@@ -39,65 +39,72 @@
%D \bTD Text 4 \eTD
%D \eTR
%D \eTABLE
-%D \stoptyping
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
%D
%D Watch how the new macros use less code:
%D
-%D \starttyping
+%D \startbuffer
%D \startTABLE
%D \NC Text 1 \NC Text 2 \NC\NR
%D \NC Text 3 \NC Text 4 \NC\NR
%D \stopTABLE
-%D \stoptyping
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
%D
%D The actual code differs from the prototype that it does not need
%D to collect whole rows and parse them but looks ahead instead.
-\def\startTABLE
- {\dosingleempty\dostartTABLE}
+\newconditional\c_tabl_nte_in_nc
-\def\dostartTABLE[#1]%
+\unexpanded\def\startTABLE
+ {\dosingleempty\tabl_nte_start}
+
+\def\tabl_nte_start[#1]%
{\bgroup
\bTABLE[#1]%
- \let\NC\doTABLENC
- \let\NR\doTABLENR
+ \let\NC\tabl_nte_start_nc
+ \let\NR\tabl_nte_start_nr
\let\bTR\relax
\let\bTD\relax
\let\bTH\relax
\let\bTN\relax}
-\def\stopTABLE
+\unexpanded\def\stopTABLE
{\eTABLE
\egroup}
-\newconditional\inTABLEnc
-
-\unexpanded\def\doTABLENR
+\unexpanded\def\tabl_nte_start_nr
{\eTR
- \setfalse\inTABLEnc}
+ \setfalse\c_tabl_nte_in_nc}
-\unexpanded\def\doTABLENC
- {\futurelet\next\dodoTABLENC}
+\unexpanded\def\tabl_nte_start_nc
+ {\futurelet\next\tabl_nte_start_nc_indeed}
-\def\dodoTABLENC
- {\ifx\next\doTABLENR \else
- \expandafter\dododoTABLENC
+\def\tabl_nte_start_nc_indeed
+ {\ifx\next\tabl_nte_start_nr \else
+ \expandafter\tabl_nte_start_nc_finish
\fi}
-\long\def\dododoTABLENC#1\NC
- {\ifconditional\inTABLEnc\else\settrue\inTABLEnc\dobTR[]\fi
- \dobTD#1\eTD\NC}
+\def\tabl_nte_start_nc_finish#1\NC
+ {\ifconditional\c_tabl_nte_in_nc \else
+ \settrue\c_tabl_nte_in_nc
+ \dobTR[]%
+ \fi
+ \dobTD#1\eTD\NC}
%D The related structure commands are also available:
-\unexpanded\def\startTABLEhead{\dosingleempty\dostartTABLEhead} \let\stopTABLEhead\relax
-\unexpanded\def\startTABLEnext{\dosingleempty\dostartTABLEnext} \let\stopTABLEnext\relax
-\unexpanded\def\startTABLEbody{\dosingleempty\dostartTABLEbody} \let\stopTABLEbody\relax
-\unexpanded\def\startTABLEfoot{\dosingleempty\dostartTABLEfoot} \let\stopTABLEfoot\relax
+\unexpanded\def\startTABLEhead{\dosingleempty\tabl_nte_start_head} \let\stopTABLEhead\relax
+\unexpanded\def\startTABLEnext{\dosingleempty\tabl_nte_start_next} \let\stopTABLEnext\relax
+\unexpanded\def\startTABLEbody{\dosingleempty\tabl_nte_start_body} \let\stopTABLEbody\relax
+\unexpanded\def\startTABLEfoot{\dosingleempty\tabl_nte_start_foot} \let\stopTABLEfoot\relax
-\long\def\dostartTABLEhead[#1]#2\stopTABLEhead{\appendtoks\doTABLEsection[#1]{#2}\to\TBLhead}
-\long\def\dostartTABLEnext[#1]#2\stopTABLEnext{\appendtoks\doTABLEsection[#1]{#2}\to\TBLnext}
-\long\def\dostartTABLEbody[#1]#2\stopTABLEbody{\appendtoks\doTABLEsection[#1]{#2}\to\TBLbody}
-\long\def\dostartTABLEfoot[#1]#2\stopTABLEfoot{\appendtoks\doTABLEsection[#1]{#2}\to\TBLfoot}
+\def\tabl_nte_start_head[#1]#2\stopTABLEhead{\appendtoks\doTABLEsection[#1]{#2}\to\TBLhead}
+\def\tabl_nte_start_next[#1]#2\stopTABLEnext{\appendtoks\doTABLEsection[#1]{#2}\to\TBLnext}
+\def\tabl_nte_start_body[#1]#2\stopTABLEbody{\appendtoks\doTABLEsection[#1]{#2}\to\TBLbody}
+\def\tabl_nte_start_foot[#1]#2\stopTABLEfoot{\appendtoks\doTABLEsection[#1]{#2}\to\TBLfoot}
\protect \endinput
diff --git a/tex/context/base/tabl-pln.mkiv b/tex/context/base/tabl-pln.mkiv
index 9e65f7e40..3638006c7 100644
--- a/tex/context/base/tabl-pln.mkiv
+++ b/tex/context/base/tabl-pln.mkiv
@@ -9,83 +9,124 @@
\writestatus{loading}{ConTeXt Table Macros / Plain Tabular}
+%D This code might become a module.
+
\unprotect
-\newif \if@@plnusetab
-\newif \if@@plncr
-\newbox \@@plntabs
-\newbox \@@plntabsyet
-\newbox \@@plntabsdone
-\newdimen \@@plntabdimen
+\newconditional \c_tabl_plain_cr
+\newconditional \c_tabl_plain_use_tab
+\newbox \b_tabl_plain_tabs
+\newbox \b_tabl_plain_tabs_yet
+\newbox \b_tabl_plain_tabs_done
+\newdimen \d_tabl_plain_tab
+
+\let\m_tabl_plain_next\relax
\def\cleartabs % visible
- {\global\setbox\@@plntabsyet\emptyhbox
- \setbox\@@plntabs\emptyhbox}
+ {\global\setbox\b_tabl_plain_tabs_yet\emptyhbox
+ \setbox\b_tabl_plain_tabs\emptyhbox}
\def\settabs % visible
- {\setbox\@@plntabs\emptyhbox
- \futurelet\next\@@plnsettabs}
+ {\setbox\b_tabl_plain_tabs\emptyhbox
+ \futurelet\m_tabl_plain_next\tabl_plain_set_tabs}
\def\tabalign % visible
- {\@@plnusetabtrue\@@plnmaketabbox}
+ {\settrue\c_tabl_plain_use_tab
+ \tabl_plain_make_tab_box}
-\let\+\tabalign % no outer here (can be overloaded)
+\ifdefined\+ \else
+ \let\+\tabalign % no outer here (can be overloaded)
+\fi
-\def\@@plnsettabs
- {\ifx\next\+%
- \def\nxt{\afterassignment\@@plnsettab\let\nxt}%
+\def\tabl_plain_set_tabs
+ {\ifx\m_tabl_plain_next\+%
+ \let\tabl_plain_nxt\tabl_plain_align
+ \else\ifx\m_tabl_plain_next\tabalign % added hh
+ \let\tabl_plain_nxt\tabl_plain_align
\else
- \let\nxt\@@plnsetcols
- \fi
- \let\next\relax
- \nxt}
+ \let\tabl_plain_nxt\tabl_plain_set_cols
+ \fi\fi
+ \let\m_tabl_plain_next\relax
+ \tabl_plain_nxt}
-\def\@@plnsettab
- {\let\nxt\relax
- \@@plnusetabfalse\@@plnmaketabbox}
+\def\tabl_plain_align
+ {\afterassignment\tabl_plain_set_tab
+ \let\tabl_plain_nxt}
-\def\@@plnsetcols#1\columns
- {\scratchcounter#1%
- \@@plntabdimen\hsize
+\def\tabl_plain_set_tab
+ {\let\tabl_plain_nxt\relax
+ \setfalse\c_tabl_plain_use_tab
+ \tabl_plain_make_tab_box}
+
+\def\tabl_plain_set_cols#1\columns
+ {\scratchcounter#1\relax
+ \d_tabl_plain_tab\hsize
\loop
- \ifnum\scratchcounter>\zerocount \@nother
+ \ifnum\scratchcounter>\zerocount
+ \tabl_plain_other
\repeat}
-\def\@nother
- {\scratchdimen\@@plntabdimen
+\def\tabl_plain_other
+ {\scratchdimen\d_tabl_plain_tab
\divide\scratchdimen\scratchcounter
- \setbox\@@plntabs\hbox{\hbox to\scratchdimen{}\unhbox\@@plntabs}%
- \advance\@@plntabdimen-\scratchdimen
+ \setbox\b_tabl_plain_tabs\hbox
+ {\hbox to\scratchdimen{}%
+ \unhbox\b_tabl_plain_tabs}%
+ \advance\d_tabl_plain_tab-\scratchdimen
\advance\scratchcounter\minusone}
-\def\@@plnmaketabbox
+\def\tabl_plain_make_tab_box
{\begingroup
- \global\setbox\@@plntabsyet\copy\@@plntabs
- \global\setbox\@@plntabsdone\emptyhbox
- \def\cr
- {\@@plncrtrue\crcr\egroup\egroup
- \if@@plnusetab\unvbox\zerocount\lastbox\fi\endgroup
- \setbox\@@plntabs\hbox{\unhbox\@@plntabsyet\unhbox\@@plntabsdone}}%
- \setbox\zerocount\vbox\bgroup\@@plncrfalse
- \ialign\bgroup&\@@plnbegintabbox##\@@plnendtabbox\crcr}
-
-\def\@@plnbegintabbox
- {\setbox\zerocount\hbox\bgroup}
-
-\def\@@plnendtabbox
- {\if@@plncr
- \egroup % now \box\zerocount holds the column
+ \let\+\tabalign % added hh
+ \global\setbox\b_tabl_plain_tabs_yet\copy\b_tabl_plain_tabs
+ \global\setbox\b_tabl_plain_tabs_done\emptyhbox
+ \let\cr\tabl_plain_cr
+ \setbox\scratchbox\vbox\bgroup
+ \setfalse\c_tabl_plain_cr
+ \ialign\bgroup
+ \aligntab
+ \tabl_plain_begin_tab_box
+ \alignmark\alignmark
+ \tabl_plain_end_tab_box
+ \crcr}
+
+\def\tabl_plain_cr
+ {\settrue\c_tabl_plain_cr
+ \crcr
+ \egroup
+ \egroup
+ \ifconditional\c_tabl_plain_use_tab
+ \unvbox\scratchbox
+ \lastbox % okay?
+ \fi
+ \endgroup
+ \setbox\b_tabl_plain_tabs\hbox
+ {\unhbox\b_tabl_plain_tabs_yet
+ \unhbox\b_tabl_plain_tabs_done}}
+
+\def\tabl_plain_begin_tab_box
+ {\setbox\scratchbox\hbox\bgroup}
+
+\def\tabl_plain_end_tab_box
+ {\ifconditional\c_tabl_plain_cr
+ \egroup % now \box\scratchbox holds the column
\else
- \hss\egroup
- \global\setbox\@@plntabsyet\hbox
- {\unhbox\@@plntabsyet\global\setbox\plusone\lastbox}% now \box\plusone holds its size
- \ifvoid\plusone
- \global\setbox\plusone\hbox to\wd\zerocount{}%
- \else
- \setbox\zerocount\hbox to\wd\plusone{\unhbox\zerocount}%
- \fi
- \global\setbox\@@plntabsdone\hbox{\box\plusone\unhbox\@@plntabsdone}%
- \fi
- \box\zerocount}
+ \hss
+ \egroup
+ \global\setbox\b_tabl_plain_tabs_yet\hbox
+ {\unhbox\b_tabl_plain_tabs_yet
+ \global\setbox\globalscratchbox\lastbox}% now \box\globalscratchbox holds its size
+ \ifvoid\globalscratchbox
+ \global\setbox\globalscratchbox\hbox to \wd\scratchbox
+ {}%
+ \else
+ \setbox\scratchbox\hbox to \wd\globalscratchbox
+ {\unhbox\scratchbox}%
+ \fi
+ \global\setbox\b_tabl_plain_tabs_done\hbox
+ {\box\globalscratchbox
+ \unhbox\b_tabl_plain_tabs_done}%
+ \fi
+ \box\scratchbox}
\protect \endinput
diff --git a/tex/context/base/tabl-tab.mkiv b/tex/context/base/tabl-tab.mkiv
index b50be8531..b9b519620 100644
--- a/tex/context/base/tabl-tab.mkiv
+++ b/tex/context/base/tabl-tab.mkiv
@@ -80,7 +80,7 @@
\appendtoks
\parindent\zeropoint
\raggedright
- \rightskip\zeropoint \!!plus 4em \relax
+ \rightskip\zeropoint \s!plus 4em \relax
\to \everytableparbox
\newskip \tablelefttabskip
@@ -854,11 +854,8 @@
\lineskiplimit\zeropoint
\lineskip \zeropoint
\tabskip \zeropoint
- \doifelsenothing\@@titextwidth
- {\halign}
- {\doifelse\@@titextwidth\v!max
- {\halign to \hsize}
- {\halign to \@@titextwidth}}%
+ \edef\p_tabl_table_textwidth{\directtablesparameter\c!textwidth}%
+ \halign \ifx\p_tabl_table_textwidth\empty \else to \ifx\p_tabl_table_textwidth\v!max \hsize \else \p_tabl_table_textwidth \fi\fi
% \the\!taTableSpread
\bgroup
\span
@@ -878,9 +875,9 @@
\def\donormaltablelineformat#1#2%
{\vrule
- \!!width \zeropoint
- \!!height\dimexpr\tablestrutheightfactor\tablestrutunit+#1\tablestrutunit\relax
- \!!depth \dimexpr\tablestrutdepthfactor \tablestrutunit+#2\tablestrutunit\relax
+ \s!width \zeropoint
+ \s!height\dimexpr\tablestrutheightfactor\tablestrutunit+#1\tablestrutunit\relax
+ \s!depth \dimexpr\tablestrutdepthfactor \tablestrutunit+#2\tablestrutunit\relax
\relax
\cr}
@@ -977,7 +974,7 @@
\def\donormaltablefullrule
{\starttablenoalign
\!ttGetHalfRuleThickness
- \hrule\!!height\scratchdimen\!!depth\scratchdimen
+ \hrule\s!height\scratchdimen\s!depth\scratchdimen
\stoptablenoalign}
\def\donormaltableshortrule % was: \!ttShortHrule
@@ -986,7 +983,7 @@
\ifx\tablecurrenthrulecolor\empty\else
\switchtocolor[\tablecurrenthrulecolor]% see *DL*
\fi
- \leaders\hrule\!!height\scratchdimen\!!depth\scratchdimen\hfill
+ \leaders\hrule\s!height\scratchdimen\s!depth\scratchdimen\hfill
\emptyhbox
\ignorespaces}
@@ -1022,7 +1019,7 @@
% SetTableToWidth -> textwidth=dimension [to dimension]
% Expand -> textwidth=max [to \hsize]
% WidenTableBy -> [spread #1]
-% \tablelefttabskip\zeropoint\!!plus1fill
+% \tablelefttabskip\zeropoint\s!plus1\s!fill
% \tablerighttabskip\tablelefttabskip
% LongLines -> [spread \hsize]
@@ -1330,26 +1327,38 @@
\newconditional\tablerepeathead
\newconditional\tablerepeattail
-
\unexpanded\def\starttable
{\bgroup
\dodoubleempty\dostarttable}
\unexpanded\def\dostarttable[#1][#2]% preamble optional-settings
{\ifsecondargument
- \getparameters[\??ti][#2]%
+ \setupcurrenttables[#2]%
\fi
\let\stoptable\dostoptable
- \doif\@@tisplit\v!auto
- {\ifinsidesplitfloat\let\@@tisplit\v!yes\fi}%
- \doifinsetelse\@@tisplit{\v!yes,\v!repeat}
- {\unexpanded\def\stoptable{\stoptables\egroup}%
- \starttables}
- {\doifelsenothing\@@tiframe
- {\ifinsidefloat\else\startbaselinecorrection\fi}
- {\startframedcontent[\@@tiframe]}%
- \postponenotes
- \firststagestarttable}%
+ \edef\p_tabl_table_split{\directtablesparameter\c!split}%
+ \edef\p_tabl_table_frame{\directtablesparameter\c!frame}%
+ \ifx\p_tabl_table_split\v!auto
+ \ifinsidesplitfloat
+ \let\p_tabl_table_split\v!yes
+ \lettablesparameter\c!split\v!yes % might be used later, best make a proper mode
+ \fi
+ \fi
+ \ifx\p_tabl_table_split\v!yes
+ \def\stoptable{\dostoptables\egroup}% not \unexpanded as we look ahead
+ \expandafter\starttables
+ \else\ifx\p_tabl_table_split\v!repeat
+ \def\stoptable{\dostoptables\egroup}% not \unexpanded as we look ahead
+ \doubleexpandafter\starttables
+ \else
+ \ifx\p_tabl_table_frame\empty
+ \ifinsidefloat\else\startbaselinecorrection\fi
+ \else
+ \startframedcontent[\p_tabl_table_frame]%
+ \fi
+ \postponenotes
+ \doubleexpandafter\firststagestarttable
+ \fi\fi
[#1]}
% We cannot define \unexpanded\def\dostoptable a ssomehow lookahead
@@ -1365,12 +1374,14 @@
\globalletempty\dotabletail
\stoptablenoalign
\dofinishtable
- \doifelsenothing\@@tiframe
- {\ifinsidefloat\else
+ \ifx\p_tabl_table_frame\empty
+ \ifinsidefloat\else
\stopbaselinecorrection
\goodbreak % compensates all the nobreaks
- \fi}
+ \fi
+ \else
\stopframedcontent
+ \fi
\egroup}
%D Before we can grab the argument, we have to make sure that
@@ -1465,7 +1476,7 @@
% \def\doverysimpletableHL % todo
% {\starttablenoalign
-% \expandafter\donormaltablefullrule\@@tiHLheight
+% \normalexpanded{\noexpand\donormaltablefullrule\m_tabl_table_HLheight}%
% \stoptablenoalign}
\def\dorestarttable#1%
@@ -1565,9 +1576,14 @@
{\bgroup
\let\stoptables\dostoptables
\splittablestrue
- \doifelse\@@tisplit\v!repeat
- {\settrue \tablerepeathead\settrue \tablerepeattail}
- {\setfalse\tablerepeathead\setfalse\tablerepeattail}%
+ \edef\p_tabl_table_split{\directtablesparameter\c!split}%
+ \ifx\p_tabl_table_split\v!repeat
+ \settrue\tablerepeathead
+ \settrue\tablerepeattail
+ \else
+ \setfalse\tablerepeathead
+ \setfalse\tablerepeattail
+ \fi
\flushnotes
\setbox\tablecontentbox\vbox\bgroup
\forgetall
@@ -1575,7 +1591,7 @@
\let\stoptables\relax % needed for \noalign
-\def\dostoptables
+\def\dostoptables % not \unexpanded as we need the lookahead (brrr)
{\dochucktableautorow % AM: before the tail, else noalign problem
\ifconditional\tablerepeattail\else\doinserttabletail\fi
\dofinishtable
@@ -1899,7 +1915,7 @@
\def\dotablevrulecommand#1% global assignments
{\doifnumberelse{#1}
{\global\tablevrulethicknessfactor#1\relax
- \global\multiply\tablevrulethicknessfactor\@@tiVLwidth\relax}
+ \global\multiply\tablevrulethicknessfactor\m_tabl_table_VLwidth\relax}
{\xdef\tablecurrentvrulecolor{#1}}}
\unexpanded\def\dotableVL
@@ -1909,7 +1925,7 @@
\def\dodotableVL[#1]%
{\global\let\tablecurrentvrulecolor\empty
- \global\tablevrulethicknessfactor\@@tiVLwidth\relax
+ \global\tablevrulethicknessfactor\m_tabl_table_VLwidth\relax
\iffirstargument
\rawprocesscommalist[#1]\dotablevrulecommand
\fi
@@ -1933,7 +1949,7 @@
\def\dotablehrulecommand#1% global assignments
{\doifnumberelse{#1}
{\global\tablehrulethicknessfactor#1\relax
- \global\multiply\tablehrulethicknessfactor\@@tiHLheight\relax}
+ \global\multiply\tablehrulethicknessfactor\m_tabl_table_HLheight\relax}
{\xdef\tablecurrenthrulecolor{#1}}}
\unexpanded\def\dotableHL
@@ -1953,7 +1969,7 @@
\writestatus\m!TABLE{change \string\MR\space into \string\SR}%
\fi\fi
\bgroup
- \global\tablehrulethicknessfactor\@@tiHLheight\relax
+ \global\tablehrulethicknessfactor\m_tabl_table_HLheight\relax
\iffirstargument
\global\let\tablecurrenthrulecolor\empty
\rawprocesscommalist[#1]\dotablehrulecommand
@@ -2004,10 +2020,10 @@
{\dochucktableautorow
\dofinishtablerow
\starttablenoalign
- \dosingleempty\dotableTB}
+ \dosingleempty\dodotableTB}
-\def\dotableTB[#1]%
- {\blank[\iffirstargument#1\else\@@tiNL\fi]%
+\def\dodotableTB[#1]%
+ {\blank[\iffirstargument#1\else\directtablesparameter\c!NL\fi]%
\nobreak
\stoptablenoalign}
@@ -2056,7 +2072,7 @@
\global\tabledrulespan#1\relax
\else
\global\tablehrulethicknessfactor#1\relax
- \global\multiply\tablehrulethicknessfactor\@@tiVLwidth\relax
+ \global\multiply\tablehrulethicknessfactor\m_tabl_table_VLwidth\relax
\fi}
{\xdef\tablecurrenthrulecolor{#1}}}
@@ -2074,7 +2090,7 @@
\writestatus\m!TABLE{change \string\MR\space into \string\SR}%
\fi\fi
\dosettableaction\tableunknownstate
- \global\tablehrulethicknessfactor\@@tiHLheight\relax
+ \global\tablehrulethicknessfactor\m_tabl_table_HLheight\relax
\global\tabledrulespan\zerocount
\iffirstargument
\global\let\tablecurrenthrulecolor\empty
@@ -2136,17 +2152,28 @@
\let\REF \dotablereformat
\to \localtabledefinitions
-\setvalue{\??ti:\c!distance:\v!none }{\dotableOpenUp00\def\LOW{\Lower6 }}
-\setvalue{\??ti:\c!distance:\v!small }{\dotableOpenUp00\def\LOW{\Lower6 }} % == baseline
-\setvalue{\??ti:\c!distance:\v!medium}{\dotableOpenUp11\def\LOW{\Lower7 }}
-\setvalue{\??ti:\c!distance:\v!big }{\dotableOpenUp22\def\LOW{\Lower8 }}
+\installcorenamespace{tables}
+\installcorenamespace{tabledistance}
+\installcorenamespace{tablealign}
+
+\installsetuponlycommandhandler \??tables {tables} % some day we can have named tables
+
+\setvalue{\??tabledistance\v!none }{\dotableOpenUp00\def\LOW{\Lower6 }}
+\setvalue{\??tabledistance\v!small }{\dotableOpenUp00\def\LOW{\Lower6 }} % == baseline
+\setvalue{\??tabledistance\v!medium}{\dotableOpenUp11\def\LOW{\Lower7 }}
+\setvalue{\??tabledistance\v!big }{\dotableOpenUp22\def\LOW{\Lower8 }}
\appendtoks
- \getvalue{\??ti:\c!distance:\@@tidistance}%
+ \expandcheckedcsname\??tabledistance{\directtablesparameter\c!distance}\v!medium
\to \localtabledefinitions
+\setvalue{\??tablealign\v!right }{\def\dotableparalignment{\raggedright}}
+\setvalue{\??tablealign\v!left }{\def\dotableparalignment{\raggedleft}}
+\setvalue{\??tablealign\v!middle }{\def\dotableparalignment{\raggedcenter}}
+\setvalue{\??tablealign\s!unknown}{\def\dotableparalignment{\notragged}}
+
\appendtoks
- \doifelse\@@tidistance\v!none
+ \doifelse{\directtablesparameter\c!distance}\v!none
{\tablerowfactor\zerocount}
{\tablerowfactor\plustwo }%
\to \localtabledefinitions
@@ -2160,31 +2187,28 @@
\@EAEAEA\dotextmodebar
\fi\fi}
-\unexpanded\def\setuptables
- {\dosingleargument\dosetuptables}
-
-\def\dosetuptables[#1]%
- {\getparameters[\??ti][#1]%
- \processaction % we have a command for this
- [\@@tialign]
- [ \v!right=>\def\dotableparalignment{\raggedright},
- \v!left=>\def\dotableparalignment{\raggedleft},
- \v!middle=>\def\dotableparalignment{\raggedcenter},
- \s!default=>\def\dotableparalignment{\notragged},
- \s!unknown=>\def\dotableparalignment{\notragged}]%
- \assignalfadimension\@@tiVL\@@tiVLwidth 246%
- \assignalfadimension\@@tiHL\@@tiHLheight246}
+\appendtoks
+ \expandcheckedcsname\??tablealign{\directtablesparameter\c!align}\s!unknown
+ \assignalfadimension{\directtablesparameter\c!VL}\m_tabl_table_VLwidth 246%
+ \assignalfadimension{\directtablesparameter\c!HL}\m_tabl_table_HLheight246%
+\to \everysetuptables
\def\dolocaltablesetup
- {\@@ticommands\relax
- \doifsomething\@@tibodyfont{\switchtobodyfont[\@@tibodyfont]}%
- \tablelinethicknessunit\dimexpr\@@tirulethickness/\tablelinethicknessfactor\relax
- \doifelse\@@tiheight\v!strut
- {\let\tablestrutheightfactor\tablestrutheightfactor}
- {\let\tablestrutheightfactor\@@tiheight}%
- \doifelse\@@tidepth\v!strut
- {\let\tablestrutdepthfactor\tablestrutdepthfactor}
- {\let\tablestrutdepthfactor\@@tidepth}%
+ {\directtablesparameter\c!commands\relax
+ \doifsomething{\directtablesparameter\c!bodyfont}{\switchtobodyfont[\directtablesparameter\c!bodyfont]}%
+ \tablelinethicknessunit\dimexpr\directtablesparameter\c!rulethickness/\tablelinethicknessfactor\relax
+ \edef\p_tabl_table_height{\directtablesparameter\c!height}%
+ \edef\p_tabl_table_depth{\directtablesparameter\c!depth}%
+ \ifx\p_tabl_table_height\v!strut
+ \let\tablestrutheightfactor\tablestrutheightfactor
+ \else
+ \let\tablestrutheightfactor\p_tabl_table_height
+ \fi
+ \ifx\p_tabl_table_depth\v!strut
+ \let\tablestrutdepthfactor\tablestrutdepthfactor
+ \else
+ \let\tablestrutdepthfactor\p_tabl_table_depth
+ \fi
\edef\tablestrutheightfactor{\withoutpt\the\dimexpr10\dimexpr\tablestrutheightfactor\points}%
\edef\tablestrutdepthfactor {\withoutpt\the\dimexpr10\dimexpr\tablestrutdepthfactor \points}%
\tablestrutunit\dimexpr\normalbaselineskip/12\relax % 12 is default bodyfont
@@ -2243,9 +2267,9 @@
%D \stopcombination
\setuptables
- [HL=\v!medium,
- VL=\v!medium,
- NL=\v!small,
+ [\c!HL=\v!medium,
+ \c!VL=\v!medium,
+ \c!NL=\v!small,
\c!frame=,
\c!align=\v!right,
\c!depth=.40, % \v!strut
@@ -2256,8 +2280,8 @@
\c!distance=\v!medium,
\c!bodyfont=,
\c!commands=,
- \c!background=\v!screen,
- \c!backgroundscreen=\@@rsscreen,
+ \c!background=\v!screen, % huh?
+ \c!backgroundscreen=\defaultbackgroundscreen,
\c!backgroundcolor=,
\c!split=\v!auto]
diff --git a/tex/context/base/tabl-tbl.lua b/tex/context/base/tabl-tbl.lua
index c48c5100d..7291facd3 100644
--- a/tex/context/base/tabl-tbl.lua
+++ b/tex/context/base/tabl-tbl.lua
@@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['tabl-tbl'] = {
license = "see context related readme files"
}
--- A couple of hacks ... easier to do in Lua than in regular
--- TeX. More will follow.
+-- A couple of hacks ... easier to do in Lua than in regular TeX. More will
+-- follow.
+
+local context, commands = context, commands
local tonumber = tonumber
local gsub, rep, sub, find = string.gsub, string.rep, string.sub, string.find
diff --git a/tex/context/base/tabl-tbl.mkiv b/tex/context/base/tabl-tbl.mkiv
index 20ddac461..0bd2fb05e 100644
--- a/tex/context/base/tabl-tbl.mkiv
+++ b/tex/context/base/tabl-tbl.mkiv
@@ -221,6 +221,8 @@
\newconstant \c_tabl_tabulate_localcolorspan
\newconstant \c_tabl_tabulate_modus
+\let\tabulatesplitlinemode\c_tabl_tabulate_splitlinemode % temp hack, we need an interface
+
\let \m_tabl_tabulate_separator_factor \empty % fraction
\newif \iftracetabulate % will become a tracker
@@ -305,7 +307,7 @@
\def\tabl_tabulate_nobreak_inject_tracer
{\red % maybe use the fast color switcher here
- \hrule\!!height.5\linewidth\!!depth.5\linewidth
+ \hrule\s!height.5\linewidth\s!depth.5\linewidth
\par
\kern-\linewidth
\nobreak}
@@ -1044,17 +1046,48 @@
\def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[]}
\def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[]}
+% \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}
+
\unexpanded\def\tabl_start_defined[#1]%
{\bgroup
\edef\currenttabulationparent{#1}%
\let\currenttabulation\currenttabulationparent
- \doifnextoptionalelse\tabl_start_defined_yes\tabl_start_defined_nop}
+ \dodoubleargument\tabl_start_defined_indeed}
+
+\def\tabl_start_defined_indeed
+ {\iffirstargument
+ \ifsecondargument
+ \doubleexpandafter\tabl_start_defined_two
+ \else
+ \doubleexpandafter\tabl_start_defined_one
+ \fi
+ \else
+ \singleexpandafter\tabl_start_defined_zero
+ \fi}
+
+\def\tabl_start_defined_one[#1][#2]%
+ {\doifassignmentelse{#1}
+ {\setuptabulation[\currenttabulation][#1]}%
+ {\edef\currenttabulation{\currenttabulation:#1}}%
+ \tabl_tabulate_start_building}
-\def\tabl_start_defined_yes[#1]%
+\def\tabl_start_defined_two[#1][#2]%
{\edef\currenttabulation{\currenttabulation:#1}%
+ \setuptabulation[\currenttabulation][#2]%
\tabl_tabulate_start_building}
-\def\tabl_start_defined_nop
+\def\tabl_start_defined_zero[#1][#2]%
{\tabl_tabulate_start_building}
% \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one
@@ -1261,11 +1294,11 @@
\tabl_tabulate_column_normal#1}
\def\tabl_tabulate_column_vruled_normal
- {\vrule\!!width\d_tabl_tabulate_vrulethickness\relax}
+ {\vrule\s!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}
+ \vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
\unexpanded\def\tabl_tabulate_column_vrule_inject_first
{\ifcase\d_tabl_tabulate_vrulethickness\else
@@ -1303,7 +1336,7 @@
\expandafter\ignorespaces % interferes with the more tricky hooks
\fi}
-\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public)
+\unexpanded\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public)
{\let#1\tabl_tabulate_column_inject_auto
\let\\\tabl_tabulate_column_inject_auto} % brrr, will go
@@ -1354,8 +1387,8 @@
\def\tabl_tabulate_hrule_inject_normal
{\hrule
- \!!height.5\d_tabl_tabulate_hrulethickness_local
- \!!depth .5\d_tabl_tabulate_hrulethickness_local
+ \s!height.5\d_tabl_tabulate_hrulethickness_local
+ \s!depth .5\d_tabl_tabulate_hrulethickness_local
\relax}
\def\tabl_tabulate_hrule_inject_colored
@@ -1390,8 +1423,8 @@
%
% \def\donormaltabulatehlinerule
% {\leaders \hrule
-% \!!height\dimexpr.5\lineheight-\strutdepth
-% \!!depth-\dimexpr.5\lineheight-\strutdepth+\d_tabl_tabulate_hrulethickness_local
+% \s!height\dimexpr.5\lineheight-\strutdepth
+% \s!depth-\dimexpr.5\lineheight-\strutdepth+\d_tabl_tabulate_hrulethickness_local
% \hfill}
%
% \def\docoloredtabulatehlinerule
@@ -1904,10 +1937,10 @@
{\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
+ \s_tabl_tabulate_pre\zeropoint
+ \s_tabl_tabulate_post\s_tabl_tabulate_first % was: \zeropoint
\global\c_tabl_tabulate_columns\zerocount
\global\c_tabl_tabulate_nofauto\zerocount
\global\c_tabl_tabulate_noflines\zerocount
@@ -2029,6 +2062,7 @@
%
\dostarttagged\t!tabulate\empty
\dostarttagged\t!tabulaterow\empty
+ \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed
\everycr\expandafter{\the\everycr\dostoptagged\dostarttagged\t!tabulaterow\empty}%
\expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
\dostoptagged
@@ -2150,6 +2184,26 @@
\let\TB\tabl_tabulate_TB
\to \everytabulate
+% %D Between alignment lines certain rules apply, and even a simple test can mess
+% %D up a table, which is why we have a special test facilityL
+% %D
+% %D \startbuffer
+% %D \starttabulate[|l|p|]
+% %D \NC 1test \NC test \NC \NR
+% %D \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
+% %D \stoptabulate
+% %D \stopbuffer
+% %D
+% %D \typebuffer \getbuffer
+%
+% \def\tableifelse#1% should be tabulatenoalign then
+% {\tablenoalign
+% {#1%
+% {\aftergroup \firstoftwoarguments}%
+% {\aftergroup\secondoftwoarguments}}}
+%
+% \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
+
%D Some new trickery:
%D
%D \startbuffer
@@ -2237,4 +2291,53 @@
% \NC \digits $@@@.@@1,@@$ \NC\NR
% \stoptabulatie
+%D Predefined categories (moved from core-mis):
+
+\definetabulate
+ [\v!legend]
+ [|emj1|i1|mR|]
+
+\setuptabulate
+ [\v!legend]
+ [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}]
+
+\definetabulate
+ [\v!legend][\v!two]
+ [|emj1|emk1|i1|mR|]
+
+\definetabulate
+ [\v!fact]
+ [|R|ecmj1|i1mR|]
+
+\setuptabulate
+ [\v!fact]
+ [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}]
+
+%D Another example:
+%D
+%D \starttyping
+%D \definetabulate
+%D [whatever]
+%D [|l|r|]
+%D
+%D \definetabulate
+%D [whatever][else]
+%D [|l|c|r|]
+%D
+%D \startwhatever
+%D \NC l \NC r \NC \NR
+%D \NC left \NC right \NC \NR
+%D \stopwhatever
+%D
+%D \startwhatever[else]
+%D \NC l \NC m \NC r \NC \NR
+%D \NC left \NC middle \NC right \NC \NR
+%D \stopwhatever
+%D
+%D \startwhatever[else][format={|c|c|c|c|}]
+%D \NC l \NC m \NC m \NC r \NC \NR
+%D \NC left \NC middle \NC middle \NC right \NC \NR
+%D \stopwhatever
+%D \stoptyping
+
\protect \endinput
diff --git a/tex/context/base/tabl-tsp.mkiv b/tex/context/base/tabl-tsp.mkiv
index 21182a988..0138697af 100644
--- a/tex/context/base/tabl-tsp.mkiv
+++ b/tex/context/base/tabl-tsp.mkiv
@@ -13,8 +13,11 @@
\writestatus{loading}{ConTeXt Table Macros / Splitting}
-%D The code in this file is move here from other places and needs
-%D a mkiv cleanup.
+%D The code in this file is moved here from other places and needs
+%D a mkiv cleanup. As it mostly targets at tables the code lives in
+%D the tabl and page namespaces.
+
+% work in progress
\unprotect
@@ -26,8 +29,6 @@
% \splitfloat [settings] {\placetable[optional args]{test}} {content}
-% 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.
@@ -55,61 +56,81 @@
%D \dorecurse{10}{\input tufte }
%D \stoptyping
-\newcount\noffloatssplits
-
-\settrue \onlyonesplitofffloat
-\setfalse\somenextsplitofffloat
+\installcorenamespace{floatsplitting}
-\newconditional\splitfloatdone
-
-\newif\ifinsidesplitfloat % will become chardef
+\installdirectcommandhandler \??floatsplitting {floatsplitting} % \??floatsplitting
-\newtoks\everysplitfloatsetup
+\setupfloatsplitting
+ [\c!conversion=\v!character, % \v!romannumerals
+ \c!lines=3,
+ \c!before=,
+ \c!inbetween=\page,
+ \c!after=]
-\def\extrasplitfloatlines{0}
+\newconditional\splitfloatfirstdone
+\newconditional\somenextsplitofffloat
+\newconditional\splitfloatdone
+\newconditional\onlyonesplitofffloat \settrue\onlyonesplitofffloat
-\let\splitfloatfinalizer\relax
+\newif \ifinsidesplitfloat % will become conditional
-\ifx\floatcaptionsuffix\undefined \else
- \let\floatcaptionsuffix\empty % will become \splitfloatcaptionsuffix
-\fi
+\newcount \noffloatssplits
+\newtoks \everysplitfloatsetup
-\unexpanded\def\setupfloatsplitting
- {\dodoubleargument\getparameters[\??si]}
+\let \extrasplitfloatlines \!!zerocount
+\let \splitfloatfinalizer \relax
+\let \floatcaptionsuffix \empty
\unexpanded\def\splitfloat
- {\dosingleempty\dosplitfloat}
+ {\dosingleempty\page_split_float}
-\def\dosplitfloat[#1]#2% nog dubbele refs
+\def\page_split_float[#1]#2% nog dubbele refs
{\bgroup
\global\setfalse\splitfloatdone
- \aftergroup\checksplitfloat
+ \aftergroup\page_split_float_check
\insidefloattrue
\insidesplitfloattrue
- \getparameters[\??si][#1]%
+ \setupcurrentfloatsplitting[#1]%
\global\noffloatssplits\zerocount
- \def\floatcaptionsuffix{\convertnumber\@@siconversion\noffloatssplits}%
- \let\extrasplitfloatlines\@@silines
+ \let\floatcaptionsuffix\page_split_float_suffix
+ \edef\extrasplitfloatlines{\floatsplittingparameter\c!lines}%
\the\everysplitfloatsetup
\def\splitfloatcommand{#2}%
\global\settrue \onlyonesplitofffloat
\global\setfalse\somenextsplitofffloat
- \dopushsavedfloats
- \@@sibefore
+ \page_floats_push_saved
+ \floatsplittingparameter\c!before
\let\next} % \bgroup
-\unexpanded\def\checksplitfloat
+\unexpanded\def\page_split_float_suffix
+ {\begingroup
+ \usefloatsplittingstyleandcolor\c!style\c!color % only the suffix
+ \convertnumber{\floatsplittingparameter\c!conversion}\noffloatssplits
+ \endgroup}
+
+\unexpanded\def\page_split_float_check
{\ifconditional\splitfloatdone
\splitfloatfinalizer % a weird place (could interfere with flushing)
\else
- \blank{\tttf \getmessage\m!floatblocks{13}\empty}\blank
+ \blank
+ \begingroup
+ \tttf \dontleavehmode \getmessage\m!floatblocks{13}\empty
+ \endgroup
+ \blank
\showmessage\m!floatblocks{13}\empty
\fi}
-\def\dodowithsplitofffloat
- {\dowithnextboxcs\dodowithsplitofffloatfinish\vbox}
+\def\page_split_float_process % nextbox
+ {\ifinsidesplitfloat
+ \expandafter\page_split_float_process_yes
+ \else
+ \expandafter\page_split_float_process_nop
+ \fi}
+
+\def\page_split_float_process_yes
+ {\dowithnextboxcs\page_split_float_process_finish\vbox}
-\def\dodowithsplitofffloatfinish
+\def\page_split_float_process_finish
{\forgetall
\dontcomplain
\global\settrue\splitfloatdone
@@ -127,26 +148,29 @@
\splitfloatcommand{\box\nextbox}%
\egroup
\ifconditional\somenextsplitofffloat
- \doifelsenothing\@@siinbetween
- {\ifconditional\splitfloatfirstdone\else\page\fi}
- \@@siinbetween
+ \edef\p_inbetween{\floatsplittingparameter\c!inbetween}%
+ \ifx\p_inbetween\empty
+ \ifconditional\splitfloatfirstdone\else\page\fi
+ \else
+ \p_inbetween
+ \fi
\else
- \@@siafter
- \dopopsavedfloats
- \doflushsavedfloats
+ \floatsplittingparameter\c!after
+ \page_floats_pop_saved
+ \page_floats_flush_saved
\fi
\global\settrue\splitfloatfirstdone}
-\def\nodowithsplitofffloat
- {\dowithnextboxcs\nodowithsplitofffloatfinish\vbox}
+\def\page_split_float_process_nop
+ {\dowithnextboxcs\page_split_float_process_nop_finish\vbox}
-\def\nodowithsplitofffloatfinish
+\def\page_split_float_process_nop_finish
{\forgetall
\dontcomplain
\box\nextbox % maybe an option to unvbox
\global\settrue\splitfloatfirstdone}
-\def\dochecksplitofffloat#1% box
+\def\page_split_float_check_content#1% box
{\ifinsidesplitfloat
% \ifdim\ht#1=\zeropoint % funny: \ifcase does not check for overflow
\ifcase\ht#1\relax
@@ -157,7 +181,7 @@
\fi
\fi}
-\def\analyzesplitfloatcaption#1% depends on page-flt .. pretty messy
+\def\page_split_float_check_caption#1% depends on page-flt .. pretty messy
{\edef\extrasplitfloatlines{\extrasplitfloatlines}%
\ifx\extrasplitfloatlines\v!auto
\bgroup
@@ -174,27 +198,15 @@
\doifnumberelse\extrasplitfloatlines\donothing{\def\extrasplitfloatlines{1}}%
\fi}
-\def\dowithsplitofffloat % nextbox
+\unexpanded\def\doifnotinsidesplitfloat
{\ifinsidesplitfloat
- \expandafter\dodowithsplitofffloat
- \else
- \expandafter\nodowithsplitofffloat
+ \expandafter\gobbleoneargument
\fi}
-\def\doifnotinsidesplitfloat
- {\ifinsidesplitfloat\expandafter\gobbleoneargument\fi}
-
-%D Some defaults:
-
-\setupfloatsplitting
- [\c!conversion=\v!character, % \v!romannumerals
- \c!lines=3,
- \c!before=,
- \c!inbetween=\page,
- \c!after=]
-
%D Table splitter, on top of previous code:
+% todo: keep tail to rest, so we need a lookahead
+
\newbox\tsplitcontent
\newbox\tsplitresult
\newbox\tsplithead
@@ -203,198 +215,216 @@
\newtoks\everyresettsplit
-\def\resettsplit{\the\everyresettsplit}
-
\appendtoks
- \def\tsplitminimumfreelines{0}%
- \def\tsplitminimumfreespace{0pt}%
- \setbox\tsplitcontent\emptyvbox
- \setbox\tsplitresult \emptyvbox
- \setbox\tsplithead \emptyvbox
- \setbox\tsplitnext \emptyvbox
- \setbox\tsplittail \emptyvbox
- \let\tsplitbeforeresult\donothing
- \let\tsplitafterresult \donothing
- \let\tsplitinbetween \donothing
- \let\tsplitbefore \donothing
- \let\tsplitafter \donothing
- \let\postprocesstsplit \donothing
+ \let \tsplitminimumfreelines\!!zerocount
+ \let \tsplitminimumfreespace\!!zeropoint
+ \setbox\tsplitcontent \emptyvbox
+ \setbox\tsplitresult \emptyvbox
+ \setbox\tsplithead \emptyvbox
+ \setbox\tsplitnext \emptyvbox
+ \setbox\tsplittail \emptyvbox
+ \let \tsplitbeforeresult \donothing
+ \let \tsplitafterresult \donothing
+ \let \tsplitinbetween \donothing
+ \let \tsplitbefore \donothing
+ \let \tsplitafter \donothing
+ \let \postprocesstsplit \donothing
\to \everyresettsplit
+\unexpanded\def\resettsplit
+ {\the\everyresettsplit}
+
\resettsplit
-% todo: keep tail to rest, so we need a lookahead
+\def\tsplitdirectwidth{\hsize}
-\newconditional\splitfloatfirstdone
+\newconditional\c_tabl_split_done
+\newconditional\c_tabl_split_head
+\newconditional\c_tabl_split_full
-\def\handletsplit
- {\analyzesplitfloatcaption{\wd\tsplitcontent}%
+\newdimen \d_tabl_split_available
+
+\unexpanded\def\handletsplit
+ {\page_split_float_check_caption{\wd\tsplitcontent}%
\global\setfalse\splitfloatfirstdone
\testpagesync % new, sync, but still tricky
[\tsplitminimumfreelines]
[\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]%
\setbox\scratchbox\vbox{\tsplitinbetween}%
\edef\tsplitinbetweenheight{\the\htdp\scratchbox}% etex
- \!!doneafalse
- \doloop
- {\ifinsidecolumns
- % brrr, assumes empty columns
- \global\setfalse\splitfloatfirstdone
- \scratchdimen\textheight
- \!!donectrue
- \else
- \ifconditional\splitfloatfirstdone
- \scratchdimen\textheight
- \!!donectrue
- \else\ifdim\pagegoal<\maxdimen
- \scratchdimen\dimexpr\pagegoal-\pagetotal\relax
- \!!donecfalse
- \else
- \scratchdimen\textheight
- \!!donectrue
- \fi\fi
- \fi
- \scratchdimen\dimexpr\scratchdimen-\tsplitinbetweenheight-\tsplitminimumfreespace-\extrasplitfloatlines\lineheight\relax
- \ifdim\htdp\tsplittail>\zeropoint
- \advance\scratchdimen-\htdp\tsplittail
- \fi
- \setbox\tsplitresult\vbox
- {\ifdim\ht\tsplithead>\zeropoint
- \unvcopy\tsplithead
+ \setfalse\c_tabl_split_done
+ \doloop\tabl_split_loop_body
+ \global\setfalse\usesamefloatnumber % new, prevent next increment
+ \global\setfalse\splitfloatfirstdone} % we can use this one for tests
+
+\def\tabl_split_loop_body
+ {\ifinsidecolumns
+ % brrr, assumes empty columns
+ \global\setfalse\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \else
+ \ifconditional\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \else\ifdim\pagegoal<\maxdimen
+ \d_tabl_split_available\dimexpr\pagegoal-\pagetotal\relax
+ \setfalse\c_tabl_split_full
+ \else
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \fi\fi
+ \fi
+ \d_tabl_split_available \dimexpr
+ \d_tabl_split_available
+ -\tsplitinbetweenheight
+ -\tsplitminimumfreespace
+ -\extrasplitfloatlines\lineheight
+ \relax
+ \ifdim\htdp\tsplittail>\zeropoint
+ \advance\d_tabl_split_available-\htdp\tsplittail
+ \fi
+ \setbox\tsplitresult\vbox
+ {\ifdim\ht\tsplithead>\zeropoint
+ \unvcopy\tsplithead
+ \tsplitinbetween
+ \fi}%
+ \ifconditional\c_tabl_split_done \else
+ \ifdim\ht\tsplitnext>\zeropoint
+ \setbox\tsplithead\box\tsplitnext
+ \fi
+ \fi
+ \settrue\c_tabl_split_done
+ \ifdim\ht\tsplitresult>\zeropoint
+ \settrue\c_tabl_split_head % table head
+ \else
+ \setfalse\c_tabl_split_head % no tablehead
+ \fi
+ \splittopskip\zeropoint
+ \doloop % inner loop
+ {\setbox\scratchbox\vsplit\tsplitcontent to \onepoint % \lineheight
+ \setbox\scratchbox\vbox{\unvbox\scratchbox}%
+ \ifdim\dimexpr\d_tabl_split_available-\htdp\scratchbox-\htdp\tsplitresult\relax>\zeropoint
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
\tsplitinbetween
- \fi}%
- \if!!donea\else\ifdim\ht\tsplitnext>\zeropoint
- \setbox\tsplithead\box\tsplitnext
- \fi\fi
- \!!doneatrue
- \ifdim\ht\tsplitresult>\zeropoint
- \!!donedtrue % table head
- \else
- \!!donedfalse % no tablehead
- \fi
- \splittopskip\zeropoint
- \doloop
- {\setbox\scratchbox\vsplit\tsplitcontent to \onepoint % \lineheight
- \setbox\scratchbox\vbox{\unvbox\scratchbox}%
- \ifdim\dimexpr\scratchdimen-\htdp\scratchbox-\htdp\tsplitresult\relax>\zeropoint
- \setbox\tsplitresult\vbox
- {\unvbox\tsplitresult
- \tsplitinbetween
- \unvbox\scratchbox}%
- \ifvoid\tsplitcontent \exitloop \fi
- \else\if!!doned
- % we only have a tablehead so far
- \setbox\tsplitresult\vbox{\unvbox\tsplitresult\unvbox\scratchbox}%
- \exitloop
- \else\if!!donec
- % we have text height available, but the (one) cell is too
- % large to fit, so, in order to avoid loops/deadcycles we do:
- \setbox\tsplitresult\vbox
- {\unvbox\tsplitresult
- \tsplitinbetween
- \unvbox\scratchbox}%
- \exitloop
- \else
- \setbox\tsplitcontent\vbox
- {\unvbox\scratchbox
- \tsplitinbetween
- \ifvoid\tsplitcontent\else\unvbox\tsplitcontent\fi}%
- \exitloop
- \fi\fi\fi
- \!!donedfalse
- \!!donecfalse}%
- \postprocesstsplit
- \dochecksplitofffloat\tsplitcontent
- \ifvoid\tsplitcontent
+ \unvbox\scratchbox}%
+ \ifvoid\tsplitcontent \exitloop \fi
+ \else\ifconditional\c_tabl_split_head
+ % we only have a tablehead so far
+ \setbox\tsplitresult\vbox{\unvbox\tsplitresult\unvbox\scratchbox}%
+ \exitloop
+ \else\ifconditional\c_tabl_split_full
+ % we have text height available, but the (one) cell is too
+ % large to fit, so, in order to avoid loops/deadcycles we do:
\setbox\tsplitresult\vbox
{\unvbox\tsplitresult
\tsplitinbetween
- \unvcopy\tsplittail}%
- \dowithsplitofffloat{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
- \doifnotinsidesplitfloat\tsplitafter
- \endgraf
+ \unvbox\scratchbox}%
\exitloop
\else
- % hack
- \ifdim\pagegoal<\maxdimen
- \global\pagegoal\dimexpr\pagegoal+\lineheight\relax % etex
- \fi
- % brrr
- \ifdim\ht\tsplitresult>\zeropoint
- \setbox\tsplitresult\vbox
- {\unvbox\tsplitresult
- \tsplitinbetween
- \unvcopy\tsplittail}%
- \dowithsplitofffloat{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
- \doifnotinsidesplitfloat\tsplitafter
- \endgraf
- \fi
- \ifinsidecolumns
- \goodbreak % was \doifnotinsidesplitfloat\goodbreak
- \else
- \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
+ \setbox\tsplitcontent\vbox
+ {\unvbox\scratchbox
+ \tsplitinbetween
+ \ifvoid\tsplitcontent\else\unvbox\tsplitcontent\fi}%
+ \exitloop
+ \fi\fi\fi
+ \setfalse\c_tabl_split_head
+ \setfalse\c_tabl_split_full}%
+ \postprocesstsplit
+ \page_split_float_check_content\tsplitcontent
+ \ifvoid\tsplitcontent
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvcopy\tsplittail}%
+ \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \doifnotinsidesplitfloat\tsplitafter
+ \endgraf
+ \exitloop
+ \else
+ % hack
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex
+ \fi
+ % brrr
+ \ifdim\ht\tsplitresult>\zeropoint
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvcopy\tsplittail}%
+ \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \doifnotinsidesplitfloat\tsplitafter
+ \endgraf
+ \fi
+ \ifinsidecolumns
+ \goodbreak % was \doifnotinsidesplitfloat\goodbreak
+ \else
+ \page % was \doifnotinsidesplitfloat\page
+ \fi
+ \global\settrue\usesamefloatnumber % new, prevent next increment
+ \fi}
%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}%
+\unexpanded\def\handledirecttsplit
+ {\page_split_float_check_caption{\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
+ \doloop\tabl_split_direct_loop_body
+ \global\setfalse\usesamefloatnumber % new, prevent next increment
\global\setfalse\splitfloatfirstdone} % we can use this one for tests
+\def\tabl_split_direct_loop_body
+ {\ifinsidecolumns
+ \global\setfalse\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \else\ifconditional\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \else\ifdim\pagegoal<\maxdimen
+ \d_tabl_split_available\dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \d_tabl_split_available\textheight
+ \fi\fi\fi
+ \d_tabl_split_available\dimexpr
+ \d_tabl_split_available
+ -\tsplitminimumfreespace
+ -\extrasplitfloatlines\lineheight
+ \relax
+ \tsplitdirectsplitter\d_tabl_split_available % also sets state
+ \ifdim\ht\tsplitresult>\zeropoint
+ \ifconditional\somenextsplitofffloat
+ \global\setfalse\onlyonesplitofffloat
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex
+ \fi
+ \page_split_float_process{\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}
+
\protect \endinput
% test cases
diff --git a/tex/context/base/tabl-xnt.mkvi b/tex/context/base/tabl-xnt.mkvi
index 35451abe0..ffa1f501e 100644
--- a/tex/context/base/tabl-xnt.mkvi
+++ b/tex/context/base/tabl-xnt.mkvi
@@ -129,7 +129,7 @@
\unexpanded\def\tabl_x_TABLE_start_indeed[#settings]%
{\bgroup
\tabl_x_prepare{#settings}%
- \edef\tabl_x_current_buffer{\x_table_default_buffer}%
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
\buff_pickup\tabl_x_current_buffer{bTABLE}{eTABLE}\relax\tabl_x_process}
\protect \endinput
diff --git a/tex/context/base/tabl-xtb.lua b/tex/context/base/tabl-xtb.lua
index 395d65a03..01b7ef9eb 100644
--- a/tex/context/base/tabl-xtb.lua
+++ b/tex/context/base/tabl-xtb.lua
@@ -25,6 +25,8 @@ this mechamism will be improved so that it can replace its older cousin.
-- todo: use linked list instead of r/c array
+local commands, context, tex, node = commands, context, tex, node
+
local texdimen = tex.dimen
local texcount = tex.count
local texbox = tex.box
@@ -391,7 +393,7 @@ function xtables.reflow_width()
for c=1,nofcolumns do
local drc = row[c]
if drc.list then
- --- flush_node_list(drc.list)
+ -- flush_node_list(drc.list)
drc.list = false
end
end
@@ -512,7 +514,6 @@ function xtables.reflow_width()
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
diff --git a/tex/context/base/tabl-xtb.mkvi b/tex/context/base/tabl-xtb.mkvi
index 2382cae21..fae4d1615 100644
--- a/tex/context/base/tabl-xtb.mkvi
+++ b/tex/context/base/tabl-xtb.mkvi
@@ -59,8 +59,6 @@
\unprotect
-% \def\v!xtable{xtable}
-
% option=stretch : equal distribution
% option={stretch,width} : proportional distribution
% option={max} : prefer max over forced width/height
@@ -97,6 +95,8 @@
\newcount\c_tabl_x_nesting
\newcount\c_tabl_x_skip_mode % 1 = skip
+\newdimen\d_tabl_x_textwidth
+
% \setupxtable[one][parent][a=b,c=d]
% \setupxtable[one] [a=b,c=d]
% \setupxtable [a=b,c=d]
@@ -111,10 +111,10 @@
\to \everysetupxtable
\setupxtable[%
- \c!nr=1,
- \c!nc=1,
- \c!nx=1, % slow
- \c!ny=1, % slow
+ \c!nr=\plusone,
+ \c!nc=\plusone,
+ \c!nx=\plusone, % slow
+ \c!ny=\plusone, % slow
\c!align=\v!table, % {\v!flushleft,\v!broad,\v!high}, % just as \bTABLE .. \eTABLE
\c!frameoffset=.5\linewidth,
\c!backgroundoffset=\v!frame,
@@ -124,7 +124,7 @@
% \c!bodyfont=,
\c!width=\v!fit,
\c!height=\v!fit,
- \c!maxwidth=8em,
+ \c!maxwidth=8\emwidth,
\c!autowidth=\v!yes, % controls framed
\c!rulethickness=\linewidth,
\c!strut=\v!yes,
@@ -137,8 +137,8 @@
% \c!footer=,
% \c!header=,
\c!spaceinbetween=,
- \c!textwidth=\hsize,
- \c!textheight=\vsize,
+ \c!textwidth=\v!local, % was \hsize,
+ \c!textheight=\vsize, % used for vertical spread
\c!distance=\zeropoint, % individual column
\c!columndistance=\zeropoint, % each column (whole table)
\c!leftmargindistance=\zeropoint, % whole table
@@ -164,7 +164,9 @@
% 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.
+% instanced \unknown\ it's not worth the trouble. Only use them when you
+% really need them and use the embeddedxtable command when nesting them.
+% Implementing nesting would be slower than not using direct buffers.
\def\tabl_x_process_buffer_directly[#name]%
{\bgroup
@@ -179,9 +181,10 @@
\def\tabl_x_process_buffer[#settings]%
{\tabl_x_prepare{#settings}%
\let\tabl_x_start_table\tabl_x_start_ignore
- \gobbleuntil\stopxtable}
+ \gobbleuntil\stopxtable} % nested xtables are not supported,
-%D A bonus: you can use the following construct inside a macro.
+%D A bonus: you have to use the following construct inside a macro or
+%D direct buffer.
\unexpanded\def\startembeddedxtable
{\dosingleempty\tabl_x_embedded_start}
@@ -211,10 +214,11 @@
\unexpanded\def\tabl_x_start_named_indeed[#settings]%
{\advance\c_tabl_x_nesting\plusone
\dostarttagged\t!table\empty
- \forgetall
\iffirstargument
\setupcurrentxtable[#settings]%
\fi
+ \tabl_x_check_textwidth
+ \forgetall
\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}}
@@ -223,17 +227,28 @@
%D Now we come to processing:
+\def\tabl_x_check_textwidth
+ {\edef\p_textwidth{\xtableparameter\c!textwidth}%
+ \ifx\p_textwidth\v!local
+ \d_tabl_x_textwidth\availablehsize
+ \else
+ \d_tabl_x_textwidth\p_textwidth
+ \fi}
+
\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}
+ \fi
+ \tabl_x_check_textwidth
+ \forgetall}
\def\tabl_x_get_buffer
{\ctxcommand{gettexbuffer("\tabl_x_current_buffer")}}
+\let\tabl_x_stop_cell\relax
+
\unexpanded\def\tabl_x_process
{\begingroup % *
\doifsomething{\xtableparameter\c!bodyfont}
@@ -242,7 +257,7 @@
{\xtableparameter\c!spaceinbetween}%
\ctxcommand{x_table_create {
option = "\xtableparameter\c!option",
- textwidth = \number\dimexpr\xtableparameter\c!textwidth,
+ textwidth = \number\d_tabl_x_textwidth,
textheight = \number\dimexpr\xtableparameter\c!textheight,
maxwidth = \number\dimexpr\xtableparameter\c!maxwidth,
lineheight = \number\openlineheight,
@@ -296,15 +311,64 @@
\else\ifinsidefloat
\tabl_x_flush_float_normal
\else
- \doifelse{\xtableparameter\c!split}\v!yes
- \tabl_x_flush_flow_split
- \tabl_x_flush_flow_normal
+ \tabl_x_flush_text_checked
\fi\fi
\ctxcommand{x_table_cleanup()}%
\dostoptagged
\resetbuffer[\tabl_x_current_buffer]%
\egroup}
+% text flow split modes
+
+\installcorenamespace{xtableflushsplit}
+
+\def\tabl_x_flush_text_checked
+ {\expandcheckedcsname\??xtableflushsplit{\xtableparameter\c!split}\v!no}
+
+% in text flow: headers and footers only once
+
+\setvalue{\??xtableflushsplit\v!yes}%
+ {\ctxcommand{x_table_flush{ method = "\v!split" }}}
+
+% in text flow: headers and footers only once
+
+\setvalue{\??xtableflushsplit\v!no}%
+ {\dontleavehmode % else no leftskip etc
+ \ctxcommand{x_table_flush{ method = "\v!normal" }}}
+
+% in text flow: headers and footers get repeated
+
+\setvalue{\??xtableflushsplit\v!repeat}%
+ {\doloop
+ {\ctxcommand{x_table_flush{ method = "\v!split", vsize = \number\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi }}%
+ \ifcase\c_tabl_x_state
+ \exitloop
+ \else
+ \page
+ \fi}}
+
+% \setvalue{\??xtableflushsplit\v!setups}%
+% {\directsetup{xtable:split:user}}
+%
+% \startsetups[xtable:split:user]
+% \doloop {
+% \xtablesplitflush % uses \xtablesplitvsize (a macro)
+% \ifcase\xtablesplitstate
+% \exitloop
+% \else
+% \page
+% \fi
+% }
+% \stopsetups
+%
+% \unexpanded\def\xtablesplitflush
+% {\ctxcommand{x_table_flush{ method = "\v!split", vsize = \number\dimexpr\xtablesplitvsize\relax}}\relax}
+%
+% \def\xtablesplitvsize
+% {\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi}
+%
+% \let\xtablesplitstate\c_tabl_x_state
+
\let\extratxtablesplitheight\zeropoint % might disappear so don't depend on it
\def\tabl_x_flush_float_normal
@@ -319,12 +383,6 @@
\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 }}}%
diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua
index 1ec38e181..37e01996d 100644
--- a/tex/context/base/task-ini.lua
+++ b/tex/context/base/task-ini.lua
@@ -20,7 +20,7 @@ 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.collections.process") -- disabled
appendaction("processors", "normalizers", "fonts.checkers.missing") -- disabled
appendaction("processors", "characters", "typesetters.cleaners.handler") -- disabled
@@ -59,7 +59,9 @@ 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", "normalizers", "nodes.handlers.export") -- disabled
+
+appendaction("shipouts", "finishers", "nodes.visualizers.handler") -- disabled
appendaction("shipouts", "finishers", "attributes.colors.handler") -- disabled
appendaction("shipouts", "finishers", "attributes.transparencies.handler") -- disabled
@@ -81,6 +83,7 @@ appendaction("math", "normalizers", "noads.handlers.tags", nil, "noh
appendaction("math", "normalizers", "noads.handlers.italics", nil, "nohead") -- disabled
appendaction("math", "builders", "builders.kernel.mlist_to_hlist") -- always on
+------------("math", "builders", "noads.handlers.italics", nil, "nohead") -- disabled
-- quite experimental (nodes.handlers.graphicvadjust might go away)
@@ -98,6 +101,7 @@ appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler")
-- speedup: only kick in when used
+disableaction("processors", "fonts.collections.process")
disableaction("processors", "fonts.checkers.missing")
disableaction("processors", "chars.handle_breakpoints")
disableaction("processors", "typesetters.cleaners.handler")
@@ -122,6 +126,7 @@ disableaction("shipouts", "attributes.effects.handler")
disableaction("shipouts", "attributes.negatives.handler")
disableaction("shipouts", "attributes.viewerlayers.handler")
disableaction("shipouts", "structures.tags.handler")
+disableaction("shipouts", "nodes.visualizers.handler")
disableaction("shipouts", "nodes.handlers.accessibility")
disableaction("shipouts", "nodes.handlers.backgrounds")
disableaction("shipouts", "nodes.handlers.cleanuppage")
diff --git a/tex/context/base/trac-ctx.lua b/tex/context/base/trac-ctx.lua
new file mode 100644
index 000000000..813443816
--- /dev/null
+++ b/tex/context/base/trac-ctx.lua
@@ -0,0 +1,36 @@
+if not modules then modules = { } end modules ['trac-ctx'] = {
+ version = 1.001,
+ comment = "companion to trac-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local commands, context = commands, context
+
+tex.trackers = tex.trackers or { }
+
+local textrackers = tex.trackers
+local register = trackers.register
+
+storage.register("tex/trackers",textrackers,"tex.trackers")
+
+local function doit(tag,v)
+ local tt = textrackers[tag]
+ if tt then
+ context.unprotect()
+ context(v and tt[1] or tt[2])
+ context.protect()
+ end
+end
+
+function commands.initializetextrackers()
+ for tag, commands in next, textrackers do
+ register(tag, function(v) doit(tag,v) end) -- todo: v,tag in caller
+ end
+end
+
+function commands.installtextracker(tag,enable,disable)
+ textrackers[tag] = { enable, disable }
+ register(tag, function(v) doit(tag,v) end) -- todo: v,tag in caller
+end
diff --git a/tex/context/base/trac-ctx.mkiv b/tex/context/base/trac-ctx.mkiv
new file mode 100644
index 000000000..4aeb99116
--- /dev/null
+++ b/tex/context/base/trac-ctx.mkiv
@@ -0,0 +1,28 @@
+
+%D \module
+%D [ file=trac-ctx,
+%D version=2012.07.13,
+%D title=\CONTEXT\ Tracing Macros,
+%D subtitle=TeX Trackers,
+%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 Tracing Macros / TeX Trackers}
+
+\registerctxluafile{trac-ctx}{1.001}
+
+\unprotect
+
+\unexpanded\def\installtextracker#1#2#3%
+ {\ctxcommand{installtextracker("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}}
+
+\appendtoks
+ \ctxcommand{initializetextrackers()}%
+\to \everyjob
+
+\protect \endinput
diff --git a/tex/context/base/trac-deb.lua b/tex/context/base/trac-deb.lua
index 87434a13d..9e724f9fa 100644
--- a/tex/context/base/trac-deb.lua
+++ b/tex/context/base/trac-deb.lua
@@ -94,6 +94,15 @@ end
function tracers.showlines(filename,linenumber,offset,errorstr)
local data = io.loaddata(filename)
+ if not data or data == "" then
+ local hash = url.hashed(filename)
+ if not hash.noscheme then
+ local ok, d, n = resolvers.loaders.byscheme(hash.scheme,filename)
+ if ok and n > 0 then
+ data = d
+ end
+ end
+ end
local lines = data and string.splitlines(data)
if lines and #lines > 0 then
-- this does not work yet as we cannot access the last lua error
@@ -134,7 +143,9 @@ function tracers.showlines(filename,linenumber,offset,errorstr)
end
function tracers.printerror(offset)
- local filename, linenumber = status.filename, tonumber(status.linenumber) or 0
+ local inputstack = resolvers.inputstack
+ local filename = inputstack[#inputstack] or status.filename
+ local linenumber = tonumber(status.linenumber) or 0
if not filename then
report_system("error not related to input file: %s ...",status.lasterrorstring)
elseif type(filename) == "number" then
diff --git a/tex/context/base/trac-deb.mkiv b/tex/context/base/trac-deb.mkiv
index 4f5f0e931..fe5dd02dc 100644
--- a/tex/context/base/trac-deb.mkiv
+++ b/tex/context/base/trac-deb.mkiv
@@ -13,7 +13,7 @@
\writestatus{loading}{ConTeXt Tracing Macros / Debugger}
-\registerctxluafile{trac-lmx}{1.001}
+%registerctxluafile{trac-lmx}{1.001}
\registerctxluafile{trac-deb}{1.001}
\unexpanded\def\breakpoint{\showdebuginfo\wait}
@@ -31,7 +31,7 @@
\unexpanded\def\enableexperiments [#1]{\ctxlua{experiments.enable("#1")}}
\unexpanded\def\disableexperiments[#1]{\ctxlua{experiments.disable("#1")}}
-\unexpanded\def\showdebuginfo{\ctxlua{lmx.showdebuginfo()}}
-\unexpanded\def\overloaderror{\ctxlua{lmx.overloaderror()}} % \enabledirectives[system.showerror]
+\unexpanded\def\showdebuginfo {\ctxlua{lmx.showdebuginfo()}}
+\unexpanded\def\overloaderror {\ctxlua{lmx.overloaderror()}} % \enabledirectives[system.showerror]
\unexpanded\def\showlogcategories {\ctxlua{logs.show()}}
diff --git a/tex/context/base/trac-fil.lua b/tex/context/base/trac-fil.lua
index bf291ff6b..8cc903e2a 100644
--- a/tex/context/base/trac-fil.lua
+++ b/tex/context/base/trac-fil.lua
@@ -6,18 +6,20 @@ if not modules then modules = { } end modules ['trac-fil'] = {
license = "see context related readme files"
}
+local rawset, tonumber, type, pcall = rawset, tonumber, type, pcall
local format, concat = string.format, table.concat
local openfile = io.open
local date = os.date
-local rawset, tonumber = rawset, tonumber
+local sortedpairs = table.sortedpairs
-local P, C, Cc, Cg, Cf, Ct, Cs = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cs
+local P, C, Cc, Cg, Cf, Ct, Cs, Carg = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cs, lpeg.Carg
+local lpegmatch = lpeg.match
local patterns = lpeg.patterns
local cardinal = patterns.cardinal
local whitespace = patterns.whitespace^0
-patterns.timestamp = Cf(Ct("") * (
+local timestamp = Cf(Ct("") * (
Cg (Cc("year") * (cardinal/tonumber)) * P("-")
* Cg (Cc("month") * (cardinal/tonumber)) * P("-")
* Cg (Cc("day") * (cardinal/tonumber)) * P(" ")
@@ -28,53 +30,65 @@ patterns.timestamp = Cf(Ct("") * (
* Cg (Cc("tminute") * (cardinal/tonumber))
)^0, rawset)
-patterns.keysvalues = Cf(Ct("") * (
+local 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)
+local statusline = Cf(Ct("") * (
+ whitespace * P("[") * Cg(Cc("timestamp") * timestamp ) * P("]")
+ * whitespace * Cg(Cc("status" ) * keysvalues)
),rawset)
+patterns.keysvalues = keysvalues
+patterns.statusline = statusline
+patterns.timestamp = timestamp
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,'"')
+local timeformat = format("[%%s%s]",os.timezone(true))
+local dateformat = "!%Y-%m-%d %H:%M:%S"
+
+function loggers.makeline(t)
+ local result = { } -- minimize time that file is open
+ result[#result+1] = format(timeformat,date(dateformat))
+ for k, v in sortedpairs(t) do
+ local tv = type(v)
+ if tv == "string" then
+ if v ~= "password" then
+ result[#result+1] = format(" %s=%q",k,v)
end
- f:write("\n")
- f:close()
- else
- bugged[filename] = true
+ elseif tv == "number" or tv == "boolean" then
+ result[#result+1] = format(" %s=%q",k,tostring(v))
end
end
+ return concat(result," ")
+end
+
+local function append(filename,...)
+ local f = openfile(filename,"a+")
+ if not f then
+ dir.mkdirs(file.dirname(filename))
+ f = openfile(filename,"a+")
+ end
+ if f then
+ f:write(...)
+ f:close()
+ return true
+ else
+ return false
+ 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.store(filename,data) -- a log service is nicer
+ if type(data) == "table"then
+ data = loggers.makeline(data)
+ end
+ pcall(append,filename,data,"\n")
+end
function loggers.collect(filename,result)
if lfs.isfile(filename) then
- local r = lpeg.match(Ct(patterns.statusline^0),io.loaddata(filename))
+ local r = lpegmatch(Ct(statusline^0),io.loaddata(filename))
if result then -- append
local nofresult = #result
for i=1,#r do
@@ -90,60 +104,78 @@ function loggers.collect(filename,result)
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" },
---~ }
+function loggers.fields(results) -- returns hash of fields with counts so that we can decide on importance
+ local fields = { }
+ if results then
+ for i=1,#results do
+ local r = results[i]
+ for k, v in next, r do
+ local f = fields[k]
+ if not f then
+ fields[k] = 1
+ else
+ fields[k] = f + 1
+ end
+ end
+ end
+ end
+ return fields
+end
+
+local template = [[<!-- log entries: begin --!>
+<table>
+<tr>%s</tr>
+%s
+</table>
+<!-- log entries: end --!>
+]]
+
+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] = format("<tr>%s</tr>",concat(scratch))
+ 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.store("test.log", { name = "whatever", more = math.random(1,100) })
+
+-- local fields = {
+-- { name = "name", align = "left" },
+-- { name = "more", align = "right" },
+-- }
+
+-- local entries = loggers.collect("test.log")
+-- local html = loggers.tohtml(entries,fields)
+
+-- inspect(entries)
+-- inspect(fields)
+-- inspect(html)
+
diff --git a/tex/context/base/trac-inf.lua b/tex/context/base/trac-inf.lua
index cbc9d13f8..6ba3d348e 100644
--- a/tex/context/base/trac-inf.lua
+++ b/tex/context/base/trac-inf.lua
@@ -13,7 +13,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
-local write_nl = texio.write_nl
+local write_nl = texio and texio.write_nl or print
statistics = statistics or { }
local statistics = statistics
@@ -96,7 +96,7 @@ statistics.elapsedtime = elapsedtime
statistics.elapsedindeed = elapsedindeed
statistics.elapsedseconds = elapsedseconds
--- general function
+-- general function .. we might split this module
function statistics.register(tag,fnc)
if statistics.enable and type(fnc) == "function" then
diff --git a/tex/context/base/trac-lmx.lua b/tex/context/base/trac-lmx.lua
index 452d03002..97938fb77 100644
--- a/tex/context/base/trac-lmx.lua
+++ b/tex/context/base/trac-lmx.lua
@@ -6,42 +6,62 @@ if not modules then modules = { } end modules ['trac-lmx'] = {
license = "see context related readme files"
}
--- todo: use lpeg instead (although not really needed)
+local type, tostring, rawget, loadstring, pcall = type, tostring, rawget, loadstring, pcall
+local format, sub, gsub = string.format, string.sub, string.gsub
+local concat = table.concat
+local P, Cc, Cs, C, Carg, lpegmatch = lpeg.P, lpeg.Cc, lpeg.Cs, lpeg.C, lpeg.Carg, lpeg.match
-local gsub, format, concat, byte = string.gsub, string.format, table.concat, string.byte
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
-local allocate = utilities.storage.allocate
+----- trace_templates = false trackers .register("lmx.templates", function(v) trace_templates = v end)
+local trace_variables = false trackers .register("lmx.variables", function(v) trace_variables = v end)
-lmx = lmx or { }
-local lmx = lmx
+local cache_templates = true directives.register("lmx.cache.templates",function(v) cache_templates = v end)
+local cache_files = true directives.register("lmx.cache.files", function(v) cache_files = v end)
-lmx.variables = allocate()
-local lmxvariables = lmx.variables
+local report_lmx = logs.reporter("lmx")
+local report_error = logs.reporter("lmx","error")
-local escapes = allocate {
- ['&'] = '&amp;',
- ['<'] = '&lt;',
- ['>'] = '&gt;',
- ['"'] = '&quot;'
-}
+lmx = lmx or { }
+local lmx = lmx
+
+-- This will change: we will just pass the global defaults as argument, but then we need
+-- to rewrite some older code or come up with an ugly trick.
--- variables
+local lmxvariables = {
+ ['title-default'] = 'ConTeXt LMX File',
+ ['color-background-green'] = '#4F6F6F',
+ ['color-background-blue'] = '#6F6F8F',
+ ['color-background-yellow'] = '#8F8F6F',
+ ['color-background-purple'] = '#8F6F8F',
+ ['color-background-body'] = '#808080',
+ ['color-background-main'] = '#3F3F3F',
+}
-lmxvariables['title-default'] = 'ConTeXt LMX File'
-lmxvariables['title'] = lmx.variables['title-default']
-lmxvariables['color-background-green'] = '#4F6F6F'
-lmxvariables['color-background-blue'] = '#6F6F8F'
-lmxvariables['color-background-yellow'] = '#8F8F6F'
-lmxvariables['color-background-purple'] = '#8F6F8F'
-lmxvariables['color-background-body'] = '#808080'
-lmxvariables['color-background-main'] = '#3F3F3F'
-lmxvariables['color-background-one'] = lmxvariables['color-background-green']
-lmxvariables['color-background-two'] = lmxvariables['color-background-blue']
+local lmxinherited = {
+ ['title'] = 'title-default',
+ ['color-background-one'] = 'color-background-green',
+ ['color-background-two'] = 'color-background-blue',
+ ['color-background-three'] = 'color-background-one',
+ ['color-background-four'] = 'color-background-two',
+}
-lmxvariables['color-background-three'] = function() return lmxvariables['color-background-one'] end
-lmxvariables['color-background-four'] = function() return lmxvariables['color-background-two'] end
+lmx.variables = lmxvariables
+lmx.inherited = lmxinherited
+
+setmetatableindex(lmxvariables,function(t,k)
+ k = lmxinherited[k]
+ while k do
+ local v = rawget(lmxvariables,k)
+ if v then
+ return v
+ end
+ k = lmxinherited[k]
+ end
+end)
-function lmx.set(key, value)
+function lmx.set(key,value)
lmxvariables[key] = value
end
@@ -49,9 +69,16 @@ function lmx.get(key)
return lmxvariables[key] or ""
end
+lmx.report = report_lmx
+
-- helpers
-local variables, result = { } -- we assume no nesting
+-- the variables table is an empty one that gets linked to a defaults table
+-- that gets passed with a creation (first time only) and that itself links
+-- to one that gets passed to the converter
+
+local variables = { } -- we assume no nesting
+local result = { } -- we assume no nesting
local function do_print(one,two,...)
if two then
@@ -61,40 +88,125 @@ local function do_print(one,two,...)
end
end
-local function do_escape(str)
- str = tostring(str)
- str = gsub(str,'&','&amp;')
- str = gsub(str,'[<>"]',escapes)
- return str
+-- Although it does not make much sense for most elements, we provide a mechanism
+-- to print wrapped content, something that is more efficient when we are constructing
+-- tables.
+
+local html = { }
+lmx.html = html
+
+function html.td(str)
+ if type(str) == "table" then
+ for i=1,#str do -- spoils t !
+ str[i] = format("<td>%s</td>",str[i] or "")
+ end
+ result[#result+1] = concat(str)
+ else
+ result[#result+1] = format("<td>%s</td>",str or "")
+ end
end
-local function do_urlescaped(str)
- return (gsub(str,"[^%a%d]",format("%%0x",byte("%1"))))
+function html.th(str)
+ if type(str) == "table" then
+ for i=1,#str do -- spoils t !
+ str[i] = format("<th>%s</th>",str[i])
+ end
+ result[#result+1] = concat(str)
+ else
+ result[#result+1] = format("<th>%s</th>",str or "")
+ end
end
-local function do_type(str)
- if str then do_print("<tt>" .. do_escape(str) .. "</tt>") end
+function html.a(text,url)
+ result[#result+1] = format("<a href=%q>%s</a>",url,text)
+end
+
+setmetatableindex(html,function(t,k)
+ local f = format("<%s>%%s</%s>",k,k)
+ local v = function(str) result[#result+1] = format(f,str or "") end
+ t[k] = v
+ return v
+end)
+
+-- Loading templates:
+
+local function loadedfile(name)
+ name = (resolvers and resolvers.findfile and resolvers.findfile(name)) or name
+ local data = io.loaddata(name)
+ if not data or data == "" then
+ report_lmx("empty file: %s",name)
+ end
+ return data
+end
+
+lmx.loadedfile = loadedfile
+
+-- A few helpers (the next one could end up in l-lpeg):
+
+local pattern = lpeg.replacer {
+ ["&"] = "&amp;",
+ [">"] = "&gt;",
+ ["<"] = "&lt;",
+ ['"'] = "&quot;",
+}
+
+local function do_escape(str)
+ return lpegmatch(pattern,str) or str
end
local function do_variable(str)
- local value = variables[str] or lmxvariables[str] -- or format("<!-- unset lmx instance variable: %s -->",str or "?")
- if type(value) == "function" then
+ local value = variables[str]
+ if not trace_variables then
+ -- nothing
+ elseif type(value) == "string" then
+ if #value > 80 then
+ report_lmx("variable %q => %s ...",str,string.collapsespaces(sub(value,1,80)))
+ else
+ report_lmx("variable %q => %s",str,string.collapsespaces(value))
+ end
+ elseif type(value) == "nil" then
+ report_lmx("variable %q => <!-- unset -->",str)
+ else
+ report_lmx("variable %q => %q",str,tostring(value))
+ end
+ if type(value) == "function" then -- obsolete ... will go away
return value(str)
else
return value
end
end
-function lmx.loadedfile(name)
- name = (resolvers and resolvers.findfile and resolvers.findfile(name)) or name
- return io.loaddata(name)
+local function do_type(str)
+ if str and str ~= "" then
+ result[#result+1] = format("<tt>%s</tt>",do_escape(str))
+ end
+end
+
+local function do_fprint(str,...)
+ if str and str ~= "" then
+ result[#result+1] = format(str,...)
+ end
end
-local function do_include(filename)
- local stylepath = do_variable('includepath') -- todo: store paths of loaded files
- local data = lmx.loadedfile(filename)
+local function do_print_variable(str)
+ local str = do_variable(str) -- variables[str]
+ if str and str ~= "" then
+ result[#result+1] = str
+ end
+end
+
+local function do_type_variable(str)
+ local str = do_variable(str) -- variables[str]
+ if str and str ~= "" then
+ result[#result+1] = format("<tt>%s</tt>",do_escape(str))
+ end
+end
+
+local function do_include(filename) -- todo: store paths of loaded files
+ local stylepath = lmxvariables.includepath
+ local data = loadedfile(filename)
if (not data or data == "") and stylepath and stylepath ~= "" then
- data = lmx.loadedfile(file.join(stylepath,filename))
+ data = loadedfile(file.join(stylepath,filename))
end
if not data or data == "" then
data = format("<!-- unknown lmx include file: %s -->",filename)
@@ -102,132 +214,400 @@ local function do_include(filename)
return data
end
+-- Flushers:
+
lmx.print = do_print
lmx.type = do_type
+lmx.fprint = do_fprint
+
lmx.escape = do_escape
-lmx.urlescape = do_escape
+lmx.urlescape = url.escape
lmx.variable = do_variable
lmx.include = do_include
-function lmx.pv(str)
- do_print(do_variable(str) or "")
+lmx.inject = do_print
+lmx.finject = do_fprint
+
+lmx.pv = do_print_variable
+lmx.tv = do_type_variable
+
+-- The next functions set up the closure.
+
+function lmx.initialize(d,v)
+ if not v then
+ setmetatableindex(d,lmxvariables)
+ if variables ~= d then
+ setmetatableindex(variables,d)
+ if trace_variables then
+ report_lmx("variables => given defaults => lmx variables")
+ end
+ elseif trace_variables then
+ report_lmx("variables == given defaults => lmx variables")
+ end
+ elseif d ~= v then
+ setmetatableindex(v,d)
+ if d ~= lmxvariables then
+ setmetatableindex(d,lmxvariables)
+ if variables ~= v then
+ setmetatableindex(variables,v)
+ if trace_variables then
+ report_lmx("variables => given variables => given defaults => lmx variables")
+ end
+ elseif trace_variables then
+ report_lmx("variables == given variables => given defaults => lmx variables")
+ end
+ else
+ if variables ~= v then
+ setmetatableindex(variables,v)
+ if trace_variables then
+ report_lmx("variabes => given variables => given defaults")
+ end
+ elseif trace_variables then
+ report_lmx("variables == given variables => given defaults")
+ end
+ end
+ else
+ setmetatableindex(v,lmxvariables)
+ if variables ~= v then
+ setmetatableindex(variables,v)
+ if trace_variables then
+ report_lmx("variables => given variables => lmx variables")
+ end
+ elseif trace_variables then
+ report_lmx("variables == given variables => lmx variables")
+ end
+ end
+ result = { }
+end
+
+function lmx.finalized()
+ local collapsed = concat(result)
+ result = { } -- free memory
+ return collapsed
+end
+
+function lmx.getvariables()
+ return variables
end
-function lmx.tv(str)
- lmx.type(do_variable(str) or "")
+function lmx.reset()
+ -- obsolete
end
+-- Creation: (todo: strip <!-- -->)
+
local template = [[
- local definitions = { }
- local p, v, e, t, pv, tv = lmx.print, lmx.variable, lmx.escape, lmx.type, lmx.pv, lmx.tv
- %s
+return function(defaults,variables)
+
+-- initialize
+
+lmx.initialize(defaults,variables)
+
+-- interface
+
+local definitions = { }
+local variables = lmx.getvariables()
+local html = lmx.html
+local inject = lmx.print
+local finject = lmx.fprint
+local escape = lmx.escape
+local verbose = lmx.type
+
+-- shortcuts (sort of obsolete as there is no gain)
+
+local p = lmx.print
+local f = lmx.fprint
+local v = lmx.variable
+local e = lmx.escape
+local t = lmx.type
+local pv = lmx.pv
+local tv = lmx.tv
+
+-- generator
+
+%s
+
+-- finalize
+
+return lmx.finalized()
+
+end
]]
+local function savedefinition(definitions,tag,content)
+ definitions[tag] = content
+ return ""
+end
+
+local function getdefinition(definitions,tag)
+ return definitions[tag] or ""
+end
+
+local whitespace = lpeg.patterns.whitespace
+local optionalspaces = whitespace^0
+
+local begincomment = P("<!--")
+local endcomment = P("-->")
+
+local beginembedxml = P("<?")
+local endembedxml = P("?>")
+
+local beginembedcss = P("/*")
+local endembedcss = P("*/")
+
+local gobbledend = (optionalspaces * endembedxml) / ""
+local argument = (1-gobbledend)^0
+
+local comment = (begincomment * (1-endcomment)^0 * endcomment) / ""
+
+local beginluaxml = (beginembedxml * P("lua")) / ""
+local endluaxml = endembedxml / ""
+
+local luacodexml = beginluaxml
+ * (1-endluaxml)^1
+ * endluaxml
+
+local beginluacss = (beginembedcss * P("lua")) / ""
+local endluacss = endembedcss / ""
+
+local luacodecss = beginluacss
+ * (1-endluacss)^1
+ * endluacss
+
+local othercode = (1-beginluaxml-beginluacss)^1 / " p[==[%0]==] "
+
+local include = ((beginembedxml * P("lmx-include") * optionalspaces) / "")
+ * (argument / lmx.include)
+ * gobbledend
+
+local define_b = ((beginembedxml * P("lmx-define-begin") * optionalspaces) / "")
+ * argument
+ * gobbledend
+
+local define_e = ((beginembedxml * P("lmx-define-end") * optionalspaces) / "")
+ * argument
+ * gobbledend
+
+local define_c = C((1-define_e)^0)
+
+local define = (Carg(1) * C(define_b) * define_c * define_e) / savedefinition
+
+local resolve = ((beginembedxml * P("lmx-resolve") * optionalspaces) / "")
+ * ((Carg(1) * C(argument)) / getdefinition)
+ * gobbledend
+
+local pattern_1 = Cs((comment + include + P(1))^0) -- get rid of comments asap
+local pattern_2 = Cs((define + resolve + P(1))^0)
+local pattern_3 = Cs((luacodexml + luacodecss + othercode)^0)
+
local cache = { }
-local trace = false
+local function lmxerror(str)
+ report_error(str)
+ return html.tt(str)
+end
+
+local function wrapper(converter,defaults,variables)
+ local outcome, message = pcall(converter,defaults,variables)
+ if not outcome then
+ return lmxerror(format("error in conversion: %s",message))
+ else
+ return message
+ end
+end
-function lmx.new(data,variables)
+function lmxnew(data,defaults,nocache) -- todo: use defaults in calling routines
data = data or ""
local known = cache[data]
if not known then
- local definitions = { }
- data = gsub(data,"<%?lmx%-include%s+(.-)%s-%?>", function(filename)
- return lmx.include(filename)
- end)
- local definitions = { }
- data = gsub(data,"<%?lmx%-define%-begin%s+(%S-)%s-%?>(.-)<%?lmx%-define%-end%s-%?>", function(tag,content)
- definitions[tag] = content
- return ""
- end)
- data = gsub(data,"<%?lmx%-resolve%s+(%S-)%s-%?>", function(tag)
- return definitions[tag] or ""
- end)
- data = gsub(data .. "<?lua ?>","(.-)<%?lua%s+(.-)%s*%?>", function(txt,lua)
- txt = gsub(txt,"%c+","\n")
- return format("p(%q)%s ",txt,lua) -- nb! space
- end)
- data = format(template,data)
+ data = lpegmatch(pattern_1,data)
+ data = lpegmatch(pattern_2,data,1,{})
+ data = lpegmatch(pattern_3,data)
+ local converted = loadstring(format(template,data))
+ if converted then
+ converted = converted()
+ end
+ defaults = defaults or { }
+ local converter
+ if converted then
+ converter = function(variables)
+ return wrapper(converted,defaults,variables)
+ end
+ else
+ converter = function() lmxerror("error in template") end
+ end
known = {
- data = trace and data,
- variables = variables or { },
- converter = loadstring(data),
+ data = defaults.trace and data or "",
+ variables = defaults,
+ converter = converter,
}
+ if cache_templates and nocache ~= false then
+ cache[data] = known
+ end
elseif variables then
known.variables = variables
end
return known, known.variables
end
-function lmx.reset(self)
- self.variables = { }
-end
-
-function lmx.result(self)
- if trace then
- return self.data
+local function lmxresult(self,variables)
+ if self then
+ local converter = self.converter
+ if converter then
+ local converted = converter(variables)
+ if trace_variables then -- will become templates
+ report_lmx("converted size: %s",#converted)
+ end
+ return converted or lmxerror("no result from converter")
+ else
+ return lmxerror("invalid converter")
+ end
else
- variables, result = self.variables, { }
- self.converter()
- return concat(result)
+ return lmxerror("invalid specification")
end
end
--- file converter
+lmx.new = lmxnew
+lmx.result = lmxresult
-local loaded = { }
+local loadedfiles = { }
-function lmx.convert(templatefile,resultfile,variables)
- local data = loaded[templatefile]
- if not data then
- data = lmx.new(lmx.loadedfile(templatefile),variables)
- loaded[template] = data
- elseif variables then
- data.variables = variables
+function lmx.convertstring(templatestring,variables,nocache)
+ return lmxresult(lmxnew(templatestring,nil,nocache),variables)
+end
+
+function lmx.convertfile(templatefile,variables,nocache)
+ if trace_variables then -- will become templates
+ report_lmx("converting file: %s",templatefile)
+ end
+ local converter = loadedfiles[templatefile]
+ if not converter then
+ converter = lmxnew(loadedfile(templatefile),nil,nocache)
+ loadedfiles[templatefile] = converter
end
- local result = lmx.result(data)
+ return lmxresult(converter,variables)
+end
+
+function lmxconvert(templatefile,resultfile,variables,nocache) -- or (templatefile,variables)
+ if trace_variables then -- will become templates
+ report_lmx("converting file: %s",templatefile)
+ end
+ if not variables and type(resultfile) == "table" then
+ variables = resultfile
+ end
+ local converter = loadedfiles[templatefile]
+ if not converter then
+ converter = lmxnew(loadedfile(templatefile),nil,nocache)
+ if cache_files then
+ loadedfiles[templatefile] = converter
+ end
+ end
+ local result = lmxresult(converter,variables)
if resultfile then
io.savedata(resultfile,result)
else
- return lmx.result(data,result)
+ return result
end
end
--- these can be overloaded; we assume that the os handles filename associations
+lmx.convert = lmxconvert
+
+-- helpers
+
+local nocomment = (beginembedcss * (1 - endembedcss)^1 * endembedcss) / ""
+local nowhitespace = whitespace^1 / " " -- ""
+local semistripped = whitespace^1 / "" * P(";")
+local stripper = Cs((nocomment + semistripped + nowhitespace + 1)^1)
-lmx.lmxfile = function(filename) return filename end -- beware, these can be set!
-lmx.htmfile = function(filename) return filename end -- beware, these can be set!
+function lmx.stripcss(str)
+ return lpegmatch(stripper,str)
+end
-if os.type == "windows" then
- lmx.popupfile = function(filename) os.execute("start " .. filename) end
-else
- lmx.popupfile = function(filename) os.execute(filename) end
+function lmx.color(r,g,b,a)
+ if r > 1 then
+ r = 1
+ end
+ if g > 1 then
+ g = 1
+ end
+ if b > 1 then
+ b = 1
+ end
+ if not a then
+ a= 0
+ elseif a > 1 then
+ a = 1
+ end
+ if a > 0 then
+ return string.format("rgba(%s%%,%s%%,%s%%,%s)",r*100,g*100,b*100,a)
+ else
+ return string.format("rgb(%s%%,%s%%,%s%%)",r*100,g*100,b*100)
+ end
end
-function lmx.make(name,variables)
+
+-- these can be overloaded
+
+lmx.lmxfile = string.itself
+lmx.htmfile = string.itself
+lmx.popupfile = os.launch
+
+function lmxmake(name,variables)
local lmxfile = lmx.lmxfile(name)
local htmfile = lmx.htmfile(name)
if lmxfile == htmfile then
- htmfile = gsub(lmxfile, "%.%a+$", "html")
+ htmfile = file.replacesuffix(lmxfile,"html")
end
- lmx.convert(lmxfile,htmfile,variables)
+ lmxconvert(lmxfile,htmfile,variables)
return htmfile
end
+lmxmake = lmx.make
+
function lmx.show(name,variables)
- local htmfile = lmx.make(name,variables)
+ local htmfile = lmxmake(name,variables)
lmx.popupfile(htmfile)
return htmfile
end
--- test
-
---~ print(lmx.result(lmx.new(io.loaddata("t:/sources/context-timing.lmx"))))
-
--- command line
+-- Command line (will become mtx-lmx):
if arg then
if arg[1] == "--show" then if arg[2] then lmx.show (arg[2]) end
elseif arg[1] == "--convert" then if arg[2] then lmx.convert(arg[2], arg[3] or "temp.html") end
end
end
+
+-- Test 1:
+
+-- inspect(lmx.result(lmx.new(io.loaddata("t:/sources/context-timing.lmx"))))
+
+-- Test 2:
+
+-- local str = [[
+-- <?lmx-include somefile.css ?>
+-- <test>
+-- <?lmx-define-begin whatever?>some content a<?lmx-define-end ?>
+-- <?lmx-define-begin somemore?>some content b<?lmx-define-end ?>
+-- <more>
+-- <?lmx-resolve whatever ?>
+-- <?lua
+-- for i=1,10 do end
+-- ?>
+-- <?lmx-resolve somemore ?>
+-- </more>
+-- <td><?lua p(100) ?></td>
+-- <td><?lua p(variables.a) ?></td>
+-- <td><?lua p(variables.b) ?></td>
+-- <td><?lua p(variables.c) ?></td>
+-- <td><?lua pv('title-default') ?></td>
+-- </test>
+-- ]]
+--
+-- local defaults = { trace = true, a = 3, b = 3 }
+-- local result = lmx.new(str,defaults)
+-- inspect(result.data)
+-- inspect(result.converter(defaults))
+-- inspect(result.converter { a = 1 })
+-- inspect(lmx.result(result, { b = 2 }))
+-- inspect(lmx.result(result, { a = 20000, b = 40000 }))
diff --git a/tex/context/base/trac-set.lua b/tex/context/base/trac-set.lua
index bc0070eb4..bac448f77 100644
--- a/tex/context/base/trac-set.lua
+++ b/tex/context/base/trac-set.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['trac-set'] = { -- might become u
license = "see context related readme files"
}
+-- maybe this should be util-set.lua
+
local type, next, tostring = type, next, tostring
local concat = table.concat
local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
@@ -205,7 +207,7 @@ function setters.show(t)
local value, default, modules = functions.value, functions.default, #functions
value = value == nil and "unset" or tostring(value)
default = default == nil and "unset" or tostring(default)
- t.report("%-30s modules: %2i default: %6s value: %6s",name,modules,default,value)
+ t.report("%-50s modules: %2i default: %6s value: %6s",name,modules,default,value)
end
end
t.report()
@@ -297,17 +299,31 @@ end)
-- experiment
-local flags = environment and environment.engineflags
+if environment then
-if flags then
- if trackers and flags.trackers then
- setters.initialize("flags","trackers", settings_to_hash(flags.trackers))
- -- t_enable(flags.trackers)
- end
- if directives and flags.directives then
- setters.initialize("flags","directives", settings_to_hash(flags.directives))
- -- d_enable(flags.directives)
+ -- The engineflags are known earlier than environment.arguments but maybe we
+ -- need to handle them both as the later are parsed differently. The c: prefix
+ -- is used by mtx-context to isolate the flags from those that concern luatex.
+
+ local engineflags = environment.engineflags
+
+ if engineflags then
+ if trackers then
+ local list = engineflags["c:trackers"] or engineflags["trackers"]
+ if type(list) == "string" then
+ setters.initialize("flags","trackers",settings_to_hash(list))
+ -- t_enable(list)
+ end
+ end
+ if directives then
+ local list = engineflags["c:directives"] or engineflags["directives"]
+ if type(list) == "string" then
+ setters.initialize("flags","directives", settings_to_hash(list))
+ -- d_enable(list)
+ end
+ end
end
+
end
-- here
diff --git a/tex/context/base/trac-tex.lua b/tex/context/base/trac-tex.lua
index 7920bd1cb..362a1dd67 100644
--- a/tex/context/base/trac-tex.lua
+++ b/tex/context/base/trac-tex.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['trac-hsh'] = {
+if not modules then modules = { } end modules ['trac-tex'] = {
version = 1.001,
comment = "companion to trac-deb.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/tex/context/base/trac-tim.lua b/tex/context/base/trac-tim.lua
index de7ceca46..adc8e01b5 100644
--- a/tex/context/base/trac-tim.lua
+++ b/tex/context/base/trac-tim.lua
@@ -59,7 +59,7 @@ end
local processed = { }
local function convert(name)
- name = ((name ~= "") and name) or progress.defaultfilename
+ name = name ~= "" and name or progress.defaultfilename
if not processed[name] then
local names, top, bot, pages, paths, keys = { }, { }, { }, 0, { }, { }
local data = io.loaddata(name .. ".lut")
diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua
new file mode 100644
index 000000000..3876d0907
--- /dev/null
+++ b/tex/context/base/trac-vis.lua
@@ -0,0 +1,859 @@
+if not modules then modules = { } end modules ['trac-vis'] = {
+ version = 1.001,
+ comment = "companion to trac-vis.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local string, number, table = string, number, table
+local node, nodes, attributes, fonts, tex = node, nodes, attributes, fonts, tex
+
+local format = string.format
+
+-- This module started out in the early days of mkiv and luatex with
+-- visualizing kerns related to fonts. In the process of cleaning up the
+-- visual debugger code it made sense to integrate some other code that
+-- I had laying around and replace the old supp-vis debugging code. As
+-- only a subset of the old visual debugger makes sense it has become a
+-- different implementation. Soms of the m-visual functionality will also
+-- be ported. The code is rather trivial. The caching is not really needed
+-- but saves upto 50% of the time needed to add visualization. Of course
+-- the overall runtime is larger because of color and layer processing in
+-- the backend (can be times as much) so the runtime is somewhat larger
+-- with full visualization enabled. In practice this will never happen
+-- unless one is demoing.
+
+-- We could use pdf literals and re stream codes but it's not worth the
+-- trouble because we would end up in color etc mess. Maybe one day I'll
+-- make a nodeinjection variant.
+
+-- todo: global switch (so no attributes)
+-- todo: maybe also xoffset, yoffset of glyph
+-- todo: inline concat (more efficient)
+
+local nodecodes = nodes.nodecodes
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local whatsit_code = nodecodes.whatsit
+local user_code = nodecodes.user
+
+local kerncodes = nodes.kerncodes
+local font_kern_code = kerncodes.fontkern
+local user_kern_code = kerncodes.userkern
+
+local gluecodes = nodes.gluecodes
+local cleaders_code = gluecodes.cleaders
+local userskip_code = gluecodes.userskip
+local space_code = gluecodes.space
+local xspace_code = gluecodes.xspace
+local leftskip_code = gluecodes.leftskip
+local rightskip_code = gluecodes.rightskip
+
+local whatsitcodes = nodes.whatsitcodes
+
+local concat_nodes = nodes.concat
+local hpack_nodes = node.hpack
+local vpack_nodes = node.vpack
+local hpack_string = typesetters.hpack
+local fast_hpack_string = typesetters.fast_hpack
+local copy_node = node.copy
+local copy_list = node.copy_list
+local free_node = node.free
+local free_node_list = node.flush_list
+local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+local unset_attribute = node.unset_attribute
+local insert_before = node.insert_before
+local insert_after = node.insert_after
+local fast_hpack = nodes.fasthpack
+
+local tex_attribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
+
+local current_font = font.current
+
+local exheights = fonts.hashes.exheights
+local emwidths = fonts.hashes.emwidths
+local pt_factor = number.dimenfactors.pt
+
+local nodepool = nodes.pool
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+local new_glue = nodepool.glue
+local new_penalty = nodepool.penalty
+
+local tracers = nodes.tracers
+local visualizers = nodes.visualizers
+
+local setcolor = tracers.colors.set
+local setlistcolor = tracers.colors.setlist
+local settransparency = tracers.transparencies.set
+local setlisttransparency = tracers.transparencies.setlist
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+-- local function setlistattribute(list,a,v)
+-- while list do
+-- set_attribute(list,a,v)
+-- list = list.next
+-- end
+-- end
+
+local a_visual = attributes.private("visual")
+local a_fontkern = attributes.private("fontkern")
+local a_layer = attributes.private("viewerlayer")
+
+local hasbit = number.hasbit
+local bit = number.bit
+local setbit = number.setbit
+local clearbit = number.clearbit
+
+local trace_hbox
+local trace_vbox
+local trace_vtop
+local trace_kern
+local trace_glue
+local trace_penalty
+local trace_fontkern
+local trace_strut
+local trace_whatsit
+local trace_user
+
+local report_visualize = logs.reporter("visualize")
+
+local modes = {
+ hbox = 1,
+ vbox = 2,
+ vtop = 4,
+ kern = 8,
+ glue = 16,
+ penalty = 32,
+ fontkern = 64,
+ strut = 128,
+ whatsit = 256,
+ glyph = 512,
+ simple = 1024,
+ simplehbox = 1024 + 1,
+ simplevbox = 1024 + 2,
+ simplevtop = 1024 + 4,
+ user = 2048,
+}
+
+local modes_makeup = { "hbox", "vbox", "kern", "glue", "penalty" }
+local modes_boxes = { "hbox", "vbox" }
+local modes_all = { "hbox", "vbox", "kern", "glue", "penalty", "fontkern", "whatsit", "glyph", "user" }
+
+local usedfont, exheight, emwidth
+local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user
+
+local enabled = false
+local layers = { }
+
+function visualizers.setfont(id)
+ usedfont = id or current_font()
+ exheight = exheights[usedfont]
+ emwidth = emwidths[usedfont]
+end
+
+local function setvisual(n,a,what) -- this will become more efficient when we have the bit lib linked in
+ if not n or n == "reset" then
+ return unsetvalue
+ elseif n == "makeup" then
+ for i=1,#modes_makeup do
+ a = setvisual(modes_makeup[i],a)
+ end
+ elseif n == "boxes" then
+ for i=1,#modes_boxes do
+ a = setvisual(modes_boxes[i],a)
+ end
+ elseif n == "all" then
+ if what == false then
+ return unsetvalue
+ else
+ for i=1,#modes_all do
+ a = setvisual(modes_all[i],a)
+ end
+ end
+ else
+ local m = modes[n]
+ if m then
+ if a == unsetvalue then
+ if what == false then
+ return unsetvalue
+ else
+ a = setbit(0,m)
+ end
+ elseif what == false then
+ a = clearbit(a,m)
+ else
+ a = setbit(a,m)
+ end
+ elseif not a then
+ return unsetvalue
+ end
+ end
+ if a == unsetvalue or a == 0 then
+ return unsetvalue
+ elseif not enabled then -- must happen at runtime (as we don't store layers yet)
+ if not usedfont then
+ -- we use a narrow monospaced font
+ visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") })
+ end
+ for mode, value in next, modes do
+ local tag = format("v_%s",mode)
+ attributes.viewerlayers.define {
+ tag = format(tag),
+ title = format("visualizer %s",mode),
+ visible = "start",
+ editable = "yes",
+ printable = "yes"
+ }
+ layers[mode] = attributes.viewerlayers.register(tag,true)
+ end
+ l_hbox = layers.hbox
+ l_vbox = layers.vbox
+ l_vtop = layers.vtop
+ l_glue = layers.glue
+ l_kern = layers.kern
+ l_penalty = layers.penalty
+ l_fontkern = layers.fontkern
+ l_strut = layers.strut
+ l_whatsit = layers.whatsit
+ l_glyph = layers.glyph
+ l_user = layers.user
+ nodes.tasks.enableaction("shipouts","nodes.visualizers.handler")
+ report_visualize("enabled")
+ enabled = true
+ end
+ return a
+end
+
+function visualizers.setvisual(n)
+ tex_attribute[a_visual] = setvisual(n,tex_attribute[a_visual])
+end
+
+function visualizers.setlayer(n)
+ tex_attribute[a_layer] = layers[n] or unsetvalue
+end
+
+commands.setvisual = visualizers.setvisual
+commands.setlayer = visualizers.setlayer
+
+function commands.visual(n)
+ context(setvisual(n,0))
+end
+
+local function set(mode,v)
+ tex_attribute[a_visual] = setvisual(mode,tex_attribute[a_visual],v)
+end
+
+for mode, value in next, modes do
+ trackers.register(format("visualizers.%s",mode), function(v) set(mode,v) end)
+end
+
+trackers.register("visualizers.reset", function(v) set("reset", v) end)
+trackers.register("visualizers.all", function(v) set("all", v) end)
+trackers.register("visualizers.makeup",function(v) set("makeup",v) end)
+trackers.register("visualizers.boxes", function(v) set("boxes", v) end)
+
+local c_positive = "trace:b"
+local c_negative = "trace:r"
+local c_zero = "trace:g"
+local c_text = "trace:s"
+local c_space = "trace:y"
+local c_skip_a = "trace:c"
+local c_skip_b = "trace:m"
+local c_glyph = "trace:o"
+
+local c_positive_d = "trace:db"
+local c_negative_d = "trace:dr"
+local c_zero_d = "trace:dg"
+local c_text_d = "trace:ds"
+local c_space_d = "trace:dy"
+local c_skip_a_d = "trace:dc"
+local c_skip_b_d = "trace:dm"
+local c_glyph_d = "trace:do"
+
+local function sometext(str,layer,color)
+ local text = fast_hpack_string(str,usedfont)
+ local size = text.width
+ local rule = new_rule(size,2*exheight,exheight/2)
+ local kern = new_kern(-size)
+ setcolor(rule,color)
+ local info = concat_nodes {
+ rule,
+ kern,
+ text,
+ }
+ setlisttransparency(info,c_zero)
+ info = fast_hpack(info)
+ if layer then
+ set_attribute(info,a_layer,layer)
+ end
+ local width = info.width
+ info.width = 0
+ info.height = 0
+ info.depth = 0
+ return info, width
+end
+
+local f_cache = { }
+
+local function fontkern(head,current)
+ local kern = current.kern
+ local info = f_cache[kern]
+ if info then
+ -- print("hit fontkern")
+ else
+ local text = fast_hpack_string(format(" %0.3f",kern*pt_factor),usedfont)
+ local rule = new_rule(emwidth/10,6*exheight,2*exheight)
+ local list = text.list
+ if kern > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif kern < 0 then
+ setlistcolor(list,c_negative_d)
+ else
+ setlistcolor(list,c_zero_d)
+ end
+ setlisttransparency(list,c_text_d)
+ settransparency(rule,c_text_d)
+ text.shift = -5 * exheight
+ info = concat_nodes {
+ rule,
+ text,
+ }
+ info = fast_hpack(info)
+ set_attribute(info,a_layer,l_fontkern)
+ info.width = 0
+ info.height = 0
+ info.depth = 0
+ f_cache[kern] = info
+ end
+ head = insert_before(head,current,copy_list(info))
+ return head, current
+end
+
+local w_cache = { }
+
+local tags = {
+ open = "FIC",
+ write = "FIW",
+ close = "FIC",
+ special = "SPE",
+ localpar = "PAR",
+ dir = "DIR",
+ pdfliteral = "PDF",
+ pdfrefobj = "PDF",
+ pdfrefxform = "PDF",
+ pdfrefximage = "PDF",
+ pdfannot = "PDF",
+ pdfstartlink = "PDF",
+ pdfendlink = "PDF",
+ pdfdest = "PDF",
+ pdfthread = "PDF",
+ pdfstartthread = "PDF",
+ pdfendthread = "PDF",
+ pdfsavepos = "PDF",
+ pdfthreaddata = "PDF",
+ pdflinkdata = "PDF",
+ pdfcolorstack = "PDF",
+ pdfsetmatrix = "PDF",
+ pdfsave = "PDF",
+ pdfrestore = "PDF",
+ latelua = "LUA",
+ closelua = "LUA",
+ cancelboundary = "CBD",
+ userdefined = "USR",
+}
+
+local function whatsit(head,current)
+ local what = current.subtype
+ local info = w_cache[what]
+ if info then
+ -- print("hit whatsit")
+ else
+ local tag = whatsitcodes[what]
+ info = sometext(format("W:%s",tag and tags[tag] or what),usedfont)
+ set_attribute(info,a_layer,l_whatsit)
+ w_cache[what] = info
+ end
+ head, current = insert_after(head,current,copy_list(info))
+ return head, current
+end
+
+local function user(head,current)
+ local what = current.subtype
+ local info = w_cache[what]
+ if info then
+ -- print("hit user")
+ else
+ info = sometext(format("U:%s",what),usedfont)
+ set_attribute(info,a_layer,l_user)
+ w_cache[what] = info
+ end
+ head, current = insert_after(head,current,copy_list(info))
+ return head, current
+end
+
+local b_cache = { }
+
+local function ruledbox(head,current,vertical,layer,what,simple)
+ local wd = current.width
+ if wd ~= 0 then
+ local ht, dp = current.height, current.depth
+ local next, prev = current.next, current.prev
+ current.next, current.prev = nil, nil
+ local linewidth = emwidth/10
+ local baseline, baseskip
+ if dp ~= 0 and ht ~= 0 then
+ if wd > 20*linewidth then
+ baseline = b_cache.baseline
+ if not baseline then
+ -- due to an optimized leader color/transparency we need to set the glue node in order
+ -- to trigger this mechanism
+ local leader = concat_nodes {
+ new_glue(2*linewidth), -- 2.5
+ new_rule(6*linewidth,linewidth,0), -- 5.0
+ new_glue(2*linewidth), -- 2.5
+ }
+ -- setlisttransparency(leader,c_text)
+ leader = fast_hpack(leader)
+ -- setlisttransparency(leader,c_text)
+ baseline = new_glue(0)
+ baseline.leader = leader
+ baseline.subtype = cleaders_code
+ baseline.spec.stretch = 65536
+ baseline.spec.stretch_order = 2
+ setlisttransparency(baseline,c_text)
+ b_cache.baseline = baseline
+ end
+ baseline = copy_list(baseline)
+ baseline = fast_hpack(baseline,wd-2*linewidth)
+ -- or new hpack node, set head and also:
+ -- baseline.width = wd
+ -- baseline.glue_set = wd/65536
+ -- baseline.glue_order = 2
+ -- baseline.glue_sign = 1
+ baseskip = new_kern(-wd+linewidth)
+ else
+ baseline = new_rule(wd-2*linewidth,linewidth,0)
+ baseskip = new_kern(-wd+2*linewidth)
+ end
+ end
+ local this
+ if not simple then
+ this = b_cache[what]
+ if not this then
+ local text = fast_hpack_string(what,usedfont)
+ this = concat_nodes {
+ new_kern(-text.width),
+ text,
+ }
+ setlisttransparency(this,c_text)
+ this = fast_hpack(this)
+ this.width = 0
+ this.height = 0
+ this.depth = 0
+ b_cache[what] = this
+ end
+ end
+ local info = concat_nodes {
+ this and copy_list(this) or nil, -- this also triggers the right mode (else sometimes no whatits)
+ new_rule(linewidth,ht,dp),
+ new_rule(wd-2*linewidth,-dp+linewidth,dp),
+ new_rule(linewidth,ht,dp),
+ new_kern(-wd+linewidth),
+ new_rule(wd-2*linewidth,ht,-ht+linewidth),
+ baseskip,
+ baseline,
+ }
+ setlisttransparency(info,c_text)
+ info = fast_hpack(info)
+ info.width = 0
+ info.height = 0
+ info.depth = 0
+ set_attribute(info,a_layer,layer)
+ local info = concat_nodes {
+ current,
+ new_kern(-wd),
+ info,
+ }
+ info = fast_hpack(info,wd)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ if next then
+ info.next = next
+ next.prev = info
+ end
+ if prev then
+ info.prev = prev
+ prev.next = info
+ end
+ if head == current then
+ return info, info
+ else
+ return head, info
+ end
+ else
+ return head, current
+ end
+end
+
+local function ruledglyph(head,current)
+ local wd = current.width
+ if wd ~= 0 then
+ local ht, dp = current.height, current.depth
+ local next, prev = current.next, current.prev
+ current.next, current.prev = nil, nil
+ local linewidth = emwidth/20
+ local baseline
+ if dp ~= 0 and ht ~= 0 then
+ baseline = new_rule(wd-2*linewidth,linewidth,0)
+ end
+ local doublelinewidth = 2*linewidth
+ local info = concat_nodes {
+ new_rule(linewidth,ht,dp),
+ new_rule(wd-doublelinewidth,-dp+linewidth,dp),
+ new_rule(linewidth,ht,dp),
+ new_kern(-wd+linewidth),
+ new_rule(wd-doublelinewidth,ht,-ht+linewidth),
+ new_kern(-wd+doublelinewidth),
+ baseline,
+ }
+ setlistcolor(info,c_glyph)
+ setlisttransparency(info,c_glyph_d)
+ info = fast_hpack(info)
+ info.width = 0
+ info.height = 0
+ info.depth = 0
+ set_attribute(info,a_layer,l_glyph)
+ local info = concat_nodes {
+ current,
+ new_kern(-wd),
+ info,
+ }
+ info = fast_hpack(info)
+ info.width = wd
+ if next then
+ info.next = next
+ next.prev = info
+ end
+ if prev then
+ info.prev = prev
+ prev.next = info
+ end
+ if head == current then
+ return info, info
+ else
+ return head, info
+ end
+ else
+ return head, current
+ end
+end
+
+local g_cache = { }
+
+local tags = {
+ -- userskip = "US",
+ lineskip = "LS",
+ baselineskip = "BS",
+ parskip = "PS",
+ abovedisplayskip = "DA",
+ belowdisplayskip = "DB",
+ abovedisplayshortskip = "SA",
+ belowdisplayshortskip = "SB",
+ leftskip = "LS",
+ rightskip = "RS",
+ topskip = "TS",
+ splittopskip = "ST",
+ tabskip = "AS",
+ spaceskip = "SS",
+ xspaceskip = "XS",
+ parfillskip = "PF",
+ thinmuskip = "MS",
+ medmuskip = "MM",
+ thickmuskip = "ML",
+ leaders = "NL",
+ cleaders = "CL",
+ xleaders = "XL",
+ gleaders = "GL",
+ -- true = "VS",
+ -- false = "HS",
+}
+
+local function ruledglue(head,current,vertical)
+ local spec = current.spec
+ local width = spec.width
+ local subtype = current.subtype
+ local amount = format("%s:%0.3f",tags[subtype] or (vertical and "VS") or "HS",width*pt_factor)
+ local info = g_cache[amount]
+ if info then
+ -- print("glue hit")
+ else
+ if subtype == space_code or subtype == xspace_code then -- not yet all space
+ info = sometext(amount,l_glue,c_space)
+ elseif subtype == leftskip_code or subtype == rightskip_code then
+ info = sometext(amount,l_glue,c_skip_a)
+ elseif subtype == userskip_code then
+ if width > 0 then
+ info = sometext(amount,l_glue,c_positive)
+ elseif width < 0 then
+ info = sometext(amount,l_glue,c_negative)
+ else
+ info = sometext(amount,l_glue,c_zero)
+ end
+ else
+ info = sometext(amount,l_glue,c_skip_b)
+ end
+ g_cache[amount] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_before(head,current,info)
+ return head, current.next
+end
+
+local k_cache = { }
+
+local function ruledkern(head,current,vertical)
+ local kern = current.kern
+ local info = k_cache[kern]
+ if info then
+ -- print("kern hit")
+ else
+ local amount = format("%s:%0.3f",vertical and "VK" or "HK",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
+ else
+ info = sometext(amount,l_kern,c_zero)
+ end
+ k_cache[kern] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_before(head,current,info)
+ return head, current.next
+end
+
+local p_cache = { }
+
+local function ruledpenalty(head,current,vertical)
+ local penalty = current.penalty
+ local info = p_cache[penalty]
+ if info then
+ -- print("penalty hit")
+ else
+ local amount = format("%s:%s",vertical and "VP" or "HP",penalty)
+ if penalty > 0 then
+ info = sometext(amount,l_penalty,c_positive)
+ elseif penalty < 0 then
+ info = sometext(amount,l_penalty,c_negative)
+ else
+ info = sometext(amount,l_penalty,c_zero)
+ end
+ p_cache[penalty] = info
+ end
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_before(head,current,info)
+ return head, current.next
+end
+
+local function visualize(head,vertical)
+ local trace_hbox = false
+ local trace_vbox = false
+ local trace_vtop = false
+ local trace_kern = false
+ local trace_glue = false
+ local trace_penalty = false
+ local trace_fontkern = false
+ local trace_strut = false
+ local trace_whatsit = false
+ local trace_glyph = false
+ local trace_simple = false
+ local trace_user = false
+ local current = head
+ local prev_trace_fontkern = nil
+ local attr = unsetvalue
+ while current do
+ local id = current.id
+ local a = has_attribute(current,a_visual) or unsetvalue
+ if a ~= attr then
+ prev_trace_fontkern = trace_fontkern
+ if a == unsetvalue then
+ trace_hbox = false
+ trace_vbox = false
+ trace_vtop = false
+ trace_kern = false
+ trace_glue = false
+ trace_penalty = false
+ trace_fontkern = false
+ trace_strut = false
+ trace_whatsit = false
+ trace_glyph = false
+ trace_simple = false
+ trace_user = false
+ else -- dead slow:
+ trace_hbox = hasbit(a, 1)
+ trace_vbox = hasbit(a, 2)
+ trace_vtop = hasbit(a, 4)
+ trace_kern = hasbit(a, 8)
+ trace_glue = hasbit(a, 16)
+ trace_penalty = hasbit(a, 32)
+ trace_fontkern = hasbit(a, 64)
+ trace_strut = hasbit(a, 128)
+ trace_whatsit = hasbit(a, 256)
+ trace_glyph = hasbit(a, 512)
+ trace_simple = hasbit(a,1024)
+ trace_user = hasbit(a,2048)
+ end
+ attr = a
+ end
+ if trace_strut then
+ set_attribute(current,a_layer,l_strut)
+ elseif id == glyph_code then
+ if trace_glyph then
+ head, current = ruledglyph(head,current)
+ end
+ elseif id == disc_code then
+ if trace_glyph then
+ local pre = current.pre
+ if pre then
+ current.pre = ruledglyph(pre,pre)
+ end
+ local post = current.post
+ if post then
+ current.post = ruledglyph(post,post)
+ end
+ local replace = current.replace
+ if replace then
+ current.replace = ruledglyph(replace,replace)
+ end
+ end
+ elseif id == kern_code then
+ local subtype = current.subtype
+ -- tricky ... we don't copy the trace attribute in node-inj (yet)
+ if subtype == font_kern_code or has_attribute(current,a_fontkern) then
+ if trace_fontkern or prev_trace_fontkern then
+ head, current = fontkern(head,current)
+ end
+ elseif subtype == user_kern_code then
+ if trace_kern then
+ head, current = ruledkern(head,current,vertical)
+ end
+ end
+ elseif id == glue_code then
+ local content = current.leader
+ if content then
+ current.leader = visualize(content,false)
+ elseif trace_glue then
+ head, current = ruledglue(head,current,vertical)
+ end
+ elseif id == penalty_code then
+ if trace_penalty then
+ head, current = ruledpenalty(head,current,vertical)
+ end
+ elseif id == disc_code then
+ current.pre = visualize(current.pre)
+ current.post = visualize(current.post)
+ current.replace = visualize(current.replace)
+ elseif id == hlist_code then
+ local content = current.list
+ if content then
+ current.list = visualize(content,false)
+ end
+ if trace_hbox then
+ head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple)
+ end
+ elseif id == vlist_code then
+ local content = current.list
+ if content then
+ current.list = visualize(content,true)
+ end
+ if trace_vtop then
+ head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple)
+ elseif trace_vbox then
+ head, current = ruledbox(head,current,true,l_vbox,"__V",trace_simple)
+ end
+ elseif id == whatsit_code then
+ if trace_whatsit then
+ head, current = whatsit(head,current)
+ end
+ elseif id == user_code then
+ if trace_whatsit then
+ head, current = user(head,current)
+ end
+ end
+ current = current.next
+ end
+ return head
+end
+
+local function freed(cache)
+ local n = 0
+ for k, v in next, cache do
+ free_node_list(v)
+ n = n + 1
+ end
+ if n == 0 then
+ return 0, cache
+ else
+ return n, { }
+ end
+end
+
+local function cleanup()
+ local hf, ng, np, nk, nw
+ nf, f_cache = freed(f_cache)
+ ng, g_cache = freed(g_cache)
+ np, p_cache = freed(p_cache)
+ nk, k_cache = freed(k_cache)
+ nw, w_cache = freed(w_cache)
+ nb, b_cache = freed(b_cache)
+ -- report_visualize("cache: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes",nf,ng,np,nk,nw,nb)
+end
+
+function visualizers.handler(head)
+ if usedfont then
+ starttiming(visualizers)
+ -- local l = tex_attribute[a_layer]
+ -- local v = tex_attribute[a_visual]
+ -- tex_attribute[a_layer] = unsetvalue
+ -- tex_attribute[a_visual] = unsetvalue
+ head = visualize(head)
+ -- tex_attribute[a_layer] = l
+ -- tex_attribute[a_visual] = v
+ -- -- cleanup()
+ stoptiming(visualizers)
+ end
+ return head, false
+end
+
+function visualizers.box(n)
+ tex.box[n].list = visualizers.handler(tex.box[n].list)
+end
+
+statistics.register("visualization time",function()
+ if enabled then
+ cleanup() -- in case we don't don't do it each time
+ return format("%s seconds",statistics.elapsedtime(visualizers))
+ end
+end)
diff --git a/tex/context/base/trac-vis.mkiv b/tex/context/base/trac-vis.mkiv
index e906bb50d..0e4993853 100644
--- a/tex/context/base/trac-vis.mkiv
+++ b/tex/context/base/trac-vis.mkiv
@@ -1,7 +1,7 @@
%D \module
-%D [ file=trac-vis, % was core-vis,
-%D version=1996.06.01,
-%D title=\CONTEXT\ Tracking Macros,
+%D [ file=trac-vis, % replaces supp-vis plus some s-* modules
+%D version=2112.06.23, % 1996.10.21,
+%D title=\CONTEXT\ Tracing Macros,
%D subtitle=Visualization,
%D author=Hans Hagen,
%D date=\currentdate,
@@ -11,711 +11,119 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This module adds some more visualization cues to the ones
-%D supplied in the support module.
+%D The old visual debugger dates from 1996 and started out as joke. In practice
+%D it's not used that often although the \type {\ruledhbox} cum suis macros come
+%D in handy when writing code. In the process of luafication some additional
+%D tracing options were tested, for instance showing font kerns. As part of the
+%D \MKIV\ cleanup the decision was made to reimplement, reintegrate and reconsider
+%D all these features. The old code is gone and the new code will get extended
+%D when needed. We still provide placeholders for some old visualization commands
+%D but they might go away.
%D
-%D %\everypar dual character, \the\everypar and \everypar=
-%D %\hrule cannot be grabbed in advance, switches mode
-%D %\vrule cannot be grabbed in advance, switches mode
-%D %
-%D %\indent only explicit ones
-%D %\noindent only explicit ones
-%D %\par only explicit ones
+%D Control over what gets visualized happens with the tracker command:
%D
-%D %\leftskip only if explicit one
-%D %\rightskip only if explicit one
-
-\writestatus{loading}{ConTeXt Tracking Macros / Visualization}
-
-\unprotect
-
-%D \macros
-%D {indent, noindent, par}
-%D
-%D \TeX\ acts upon paragraphs. In mosts documents paragraphs
-%D are separated by empty lines, which internally are handled as
-%D \type{\par}. Paragraphs can be indented or not, depending on
-%D the setting of \type{\parindent}, the first token of a
-%D paragraph and/or user suppressed or forced indentation.
-%D
-%D Because the actual typesetting is based on both explicit
-%D user and implicit system actions, visualization is only
-%D possible for the user supplied \type{\indent},
-%D \type{\noindent}, and \type{\par}. Other
-%D 'clever' tricks will quite certainly lead to more failures
-%D than successes, so we only support these three explicit
-%D primitives and one macro:
-
-\def\showparagraphcue#1#2#3#4#5%
- {\bgroup
- \scratchdimen#1\relax
- \dontinterfere
- \dontcomplain
- \boxrulewidth5\testrulewidth
- #3#4\relax
- \setbox\scratchbox\normalhbox to \scratchdimen
- {#2{\ruledhbox to \scratchdimen
- {\vrule #5 20\testrulewidth \!!width \zeropoint
- \normalhss}}}%
- \smashbox\scratchbox
- \normalpenalty\plustenthousand
- \box\scratchbox
- \egroup}
-
-\def\ruledhanging
- {\ifdim\hangindent>\zeropoint
- \ifnum\hangafter<\zerocount
- \normalhbox
- {\boxrulewidth5\testrulewidth
- \setbox\scratchbox\ruledhbox to \hangindent
- {\scratchdimen\strutht
- \advance\scratchdimen \strutdp
- \vrule
- \!!width \zeropoint
- \!!height \zeropoint
- \!!depth -\hangafter\scratchdimen}%
- \normalhskip-\hangindent
- \smashbox\scratchbox
- \raise\strutht\box\scratchbox}%
- \fi
- \fi}
-
-\def\ruledparagraphcues
- {\bgroup
- \dontcomplain
- \normalhbox to \zeropoint
- {\ifdim\leftskip>\zeropoint\relax
- \showparagraphcue\leftskip\llap\relax\relax\!!depth
- \normalhskip-\leftskip
- \fi
- \ruledhanging
- \normalhskip\hsize
- \ifdim\rightskip>\zeropoint\relax
- \normalhskip-\rightskip
- \showparagraphcue\rightskip\relax\relax\relax\!!depth
- \fi}%
- \egroup}
-
-\def\ruledpar
- {\relax
- \ifhmode
- \showparagraphcue{40\testrulewidth}\relax\rightrulefalse\relax\!!height
- \fi
- \normalpar}
-
-\def\rulednoindent
- {\relax
- \normalnoindent
- \ruledparagraphcues
- \showparagraphcue{40\testrulewidth}\llap\leftrulefalse\relax\!!height}
-
-\def\ruledindent
- {\relax
- \normalnoindent
- \ruledparagraphcues
- \ifdim\parindent>\zeropoint
- \showparagraphcue\parindent\relax\relax\relax\!!height
- \else
- \showparagraphcue{40\testrulewidth}\llap\relax\relax\!!height
- \fi
- \normalhskip\parindent}
-
-\def\dontshowimplicits
- {\let\noindent \normalnoindent
- \let\indent \normalindent
- \let\par \normalpar}
-
-\def\showimplicits
- {\testrulewidth \defaulttestrulewidth
- \let\noindent \rulednoindent
- \let\indent \ruledindent
- \let\par \ruledpar}
-
-%D The next few||line examples show the four cues. Keep in
-%D mind that we only see them when we explicitly open or close
-%D a paragraph.
-%D
-%D \bgroup
-%D \def\voorbeeld#1%
-%D {#1Visualizing some \TeX\ primitives and Plain \TeX\
-%D macros can be very instructive, at least it is to me.
-%D Here we see {\tt\string#1} and {\tt\string\ruledpar} in
-%D action, while {\tt\string\parindent} equals
-%D {\tt\the\parindent}.\ruledpar}
-%D
-%D \showimplicits
-%D
-%D \voorbeeld \indent
-%D \voorbeeld \noindent
-%D
-%D \parindent=60pt
-%D
-%D \voorbeeld \indent
-%D \voorbeeld \noindent
-%D
-%D \startnarrower
-%D \voorbeeld \indent
-%D \voorbeeld \noindent
-%D \stopnarrower
-%D \egroup
-%D
-%D These examples also demonstrate the visualization of
-%D \type {\leftskip} and \type {\rightskip}. The macro
-%D \type {\nofruledbaselines} determines the number of lines
-%D shown.
-
-\newcounter\ruledbaselines
-
-\def\nofruledbaselines{3}
-
-\def\debuggertext#1%
- {\ifx\ttxx\undefined
- $\scriptscriptstyle#1$%
- \else
- {\ttxx#1}%
- \fi}
-
-\def\ruledbaseline
- {\vrule \!!width \zeropoint
- \bgroup
- \dontinterfere
- \doglobal\increment\ruledbaselines
- \scratchdimen\nofruledbaselines\baselineskip
- \setbox\scratchbox\normalvbox to 2\scratchdimen
- {\leaders
- \normalhbox
- {\strut
- \vrule
- \!!height \testrulewidth
- \!!depth \testrulewidth
- \!!width 120\points}
- \normalvfill}%
- \smashbox\scratchbox
- \advance\scratchdimen \strutheightfactor\baselineskip
- \setbox\scratchbox\normalhbox
- {\normalhskip -48\points
- \normalhbox to 24\points
- {\normalhss\debuggertext\ruledbaselines\normalhskip6\points}%
- \raise\scratchdimen\box\scratchbox}%
- \smashbox\scratchbox
- \box\scratchbox
- \egroup}
-
-\def\showbaselines
- {\testrulewidth\defaulttestrulewidth
- \EveryPar{\ruledbaseline}}
-
-%D \macros
-%D {showpagebuilder}
-%D
-%D The next tracing option probaly is only of use to me and a
-%D few \CONTEXT\ hackers.
-
-\def\showpagebuilder
- {\EveryPar{\doshowpagebuilder}}
-
-\def\doshowpagebuilder
- {\strut\llap
- {\startcolor[blue]\vl
- \high{\infofont v:\the\vsize }\vl
- \high{\infofont g:\the\pagegoal }\vl
- \high{\infofont t:\the\pagetotal}\vl
- \stopcolor}}
-
-%D \macros
-%D {makecutbox, cuthbox, cutvbox, cutvtop}
-%D
-%D Although mainly used for marking the page, these macros can
-%D also serve local use.
-%D
-%D \startbuffer
-%D \setbox0=\vbox{a real \crlf vertical box} \makecutbox0
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D This marked \type{\vbox} shows up as:
-%D
-%D \startlinecorrection
-%D \getbuffer
-%D \stoplinecorrection
-%D
-%D The alternative macros are used as:
-%D
-%D \startbuffer
-%D \cuthbox{a made cut box}
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D This is typeset as:
-%D
-%D \startlinecorrection
-%D \getbuffer
-%D \stoplinecorrection
-%D
-%D By setting the next macros one can influence the length of
-%D the marks as well as the horizontal and vertical divisions.
-
-\newdimen\tractempwidth
-\newdimen\tractempheight
-\newdimen\tractempdepth
-
-\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 \cutmarkhoffset \empty
-\let \cutmarkvoffset \empty
-
-\def\horizontalcuts
- {\normalhbox to \tractempwidth
- {\dorecurse\horizontalcutmarks{\vrule\!!width\boxrulewidth\!!height\cutmarklength\normalhfill}%
- \unskip}}
-
-\def\verticalcuts
- {\normalvbox to \dimexpr\tractempheight+\tractempdepth\relax
- {\hsize\cutmarklength
- \dorecurse\verticalcutmarks{\vrule\!!height\boxrulewidth\!!width\hsize\normalvfill}%
- \unskip}}
-
-\def\baselinecuts
- {\ifdim\tractempdepth>\zeropoint
- \normalvbox to \dimexpr\tractempheight+\tractempdepth\relax
- {\hsize\dimexpr\cutmarklength/2\relax
- \normalvskip\zeropoint\!!plus\tractempheight
- \vrule\!!height\boxrulewidth\!!width\hsize
- \normalvskip\zeropoint\!!plus\tractempdepth}%
- \fi}
-
-\def\cutmarksymbols#1%
- {\normalhbox to \tractempwidth
- {\setbox\scratchbox\normalhbox to \cutmarklength
- {\normalhss\infofont\cutmarksymbol\normalhss}%
- \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\scratchskip}%
- \normalhskip\scratchdimen\hss\infofont#1\hss\normalhskip\scratchdimen
- \rlap{\normalhskip\scratchskip\copy\scratchbox}}%
- \normalvss}%
- \normalhss}}
-
-\def\makecutbox#1% simplier with layers, todo
- {\tractempheight\ht#1%
- \tractempdepth \dp#1%
- \tractempwidth \wd#1%
- \setbox#1\normalhbox
- {\dontcomplain
- \forgetall
- \boxmaxdepth\maxdimen
- \offinterlineskip
- \scratchdimen\dimexpr\cutmarklength/2\relax
- \hsize\tractempwidth
- \setbox\scratchbox\normalvbox
- {\setbox\scratchbox\normalhbox{\horizontalcuts}%
- \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
- {\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
- \startcolor[\defaulttextcolor]%
- \box\scratchbox
- \ifx\cutmarksymbol\relax \else
- \setbox\scratchbox\normalvbox
- {\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
- \vskip-\scratchskip
- \vskip-\cutmarklength
- \normalhbox{\cutmarksymbols\cutmarktoptext}%
- \vskip\scratchskip
- \vskip\tractempheight
- \vskip\tractempdepth
- \vskip\scratchskip
- \normalhbox{\cutmarksymbols\cutmarkbottomtext}}%
- \ht\scratchbox\tractempheight
- \dp\scratchbox\tractempdepth
- \wd\scratchbox\zeropoint
- \box\scratchbox
- \fi
- \stopcolor
- \box#1}%
- \wd#1\tractempwidth
- \ht#1\tractempheight
- \dp#1\tractempdepth}
-
-\def\cuthbox{\normalhbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalhbox}
-\def\cutvbox{\normalvbox\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvbox}
-\def\cutvtop{\normalvtop\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\normalvtop}
-
-%D \macros
-%D {colormarkbox,rastermarkbox}
-%D
-%D This macro is used in the pagebody routine. No other use
-%D is advocated here.
-%D
-%D \starttyping
-%D \colormarkbox0
-%D \stoptyping
-
-\def\colormarkoffset{\cutmarkoffset}
-\def\colormarklength{\cutmarklength}
-
-\def\dodocolorrangeA#1%
- {\fastcolored[#1]{\hrule\!!width3em\!!height\scratchdimen\!!depth\zeropoint}}
-
-\def\docolorrangeA#1 #2 %
- {\vbox
- {\hsize3em % \scratchdimen
- \ifcase#1\or
- \dodocolorrangeA{c=#2}\or
- \dodocolorrangeA{m=#2}\or
- \dodocolorrangeA{y=#2}\or
- \dodocolorrangeA{m=#2,y=#2}\or
- \dodocolorrangeA{c=#2,y=#2}\or
- \dodocolorrangeA{c=#2,m=#2}\fi
- \ifdim\scratchdimen>1ex
- \vskip-\scratchdimen
- \vbox to \scratchdimen
- {\vss\hbox to 3em{\hss#2\hss}\vss}%
- \fi}}
-
-\def\colorrangeA#1%
- {\vbox
- {\startcolor[\s!white]%
- \scratchdimen\dimexpr(-\colormarklength*4+\tractempheight+\tractempdepth)/21\relax
- \offinterlineskip
- \docolorrangeA #1 1.00 \docolorrangeA #1 0.95
- \docolorrangeA #1 0.75
- \docolorrangeA #1 0.50
- \docolorrangeA #1 0.25 \docolorrangeA #1 0.05
- \docolorrangeA #1 0.00
- \stopcolor}}
-
-\def\docolorrangeB #1 #2 #3 #4 #5 %
- {\fastcolored
- [\c!c=#2,\c!m=#3,\c!y=#4,\c!k=#5]
- {\vrule\!!width\scratchdimen\!!height\colormarklength\!!depth\zeropoint}%
- \ifdim\scratchdimen>2em
- \hskip-\scratchdimen
- \vbox to \colormarklength
- {\vss\hbox to \scratchdimen{\hss#1\hss}\vss}%
- \fi}
-
-\def\colorrangeB
- {\hbox
- {\startcolor[\s!white]%
- \scratchdimen\dimexpr(-\colormarklength*\plustwo+\tractempwidth)/11\relax
- \docolorrangeB .5~C .5 0 0 0
- \docolorrangeB .5~M 0 .5 0 0
- \docolorrangeB .5~Y 0 0 .5 0
- \docolorrangeB .5~K 0 0 0 .5
- \docolorrangeB C 1 0 0 0
- \docolorrangeB G 1 0 1 0
- \docolorrangeB Y 0 0 1 0
- \docolorrangeB R 0 1 1 0
- \docolorrangeB M 0 1 0 0
- \docolorrangeB B 1 1 0 0
- \docolorrangeB K 0 0 0 1
- \stopcolor}}
-
-\def\docolorrangeC#1 %
- {\fastcolored
- [\c!s=#1]%
- {\vrule\!!width\scratchdimen\!!height\colormarklength\!!depth\zeropoint}%
- \ifdim\scratchdimen>2em
- \hskip-\scratchdimen
- \vbox to \colormarklength
- {\vss\hbox to \scratchdimen{\hss#1\hss}\vss}%
- \fi}
-
-\def\colorrangeC
- {\hbox
- {\startcolor[\s!white]%
- \scratchdimen\dimexpr(-\colormarklength*2+\tractempwidth)/14\relax
- \docolorrangeC 1 \docolorrangeC .95
- \docolorrangeC .9 \docolorrangeC .85
- \docolorrangeC .8 \docolorrangeC .75
- \docolorrangeC .7
- \docolorrangeC .6
- \docolorrangeC .5
- \docolorrangeC .4
- \docolorrangeC .3
- \docolorrangeC .2
- \docolorrangeC .1
- \docolorrangeC 0
- \stopcolor}}
-
-\def\docolormarkbox#1#2%
- {\tractempheight\ht#2%
- \tractempdepth \dp#2%
- \tractempwidth \wd#2%
- \setbox#2\hbox
- {\scratchdimen\dimexpr\colormarklength/2\relax
- \forgetall
- \ssxx
- \setbox\scratchbox\vbox
- {\offinterlineskip
- \vskip\dimexpr-\colormarkoffset\scratchdimen-2\scratchdimen\relax
- \ifcase#1\relax
- \vskip\dimexpr\colormarklength+\scratchdimen+\tractempheight\relax
- \else
- \hbox to \tractempwidth{\hss\hbox{\colorrangeB}\hss}%
- \vskip\colormarkoffset\scratchdimen
- \vbox to \tractempheight
- {\vss
- \hbox to \tractempwidth
- {\llap{\colorrangeA1\hskip\colormarkoffset\scratchdimen}\hfill
- \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA4}}%
- \vss
- \hbox to \tractempwidth
- {\llap{\colorrangeA2\hskip\colormarkoffset\scratchdimen}\hfill
- \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA5}}%
- \vss
- \hbox to \tractempwidth
- {\llap{\colorrangeA3\hskip\colormarkoffset\scratchdimen}\hfill
- \rlap{\hskip\colormarkoffset\scratchdimen\colorrangeA6}}%
- \vss}%
- \fi
- \vskip\colormarkoffset\scratchdimen
- \hbox to \tractempwidth
- {\hss\lower\tractempdepth\hbox{\colorrangeC}\hss}}%
- \ht\scratchbox\tractempheight
- \dp\scratchbox\tractempdepth
- \wd\scratchbox\zeropoint
- \box\scratchbox
- \box#2}%
- \wd#2\tractempwidth
- \ht#2\tractempheight
- \dp#2\tractempdepth}
-
-\def\colormarkbox {\docolormarkbox\plusone } % #1
-\def\rastermarkbox{\docolormarkbox\zerocount} % #1
-
-%D \macros
-%D {showwhatsits, dontshowwhatsits}
-%D
-%D \TEX\ has three so called whatsits: \type {\mark}, \type
-%D {\write} and \type {\special}. The first one keeps track of
-%D the current state at page boundaries, the last two are used
-%D to communicate to the outside world. Due to fact that
-%D especially \type {\write} is often used in conjunction with
-%D \type {\edef}, we can only savely support that one in \ETEX.
-%D
-%D \bgroup \showwhatsits \setupcolors[state=start]
+%D \enabletrackers[visualizer.*]
%D
-%D Whatsits show up \color[blue]{in color} and are
-%D characterized bij their first character.\footnote [some note]
-%D {So we may encounter \type {w}, \type {m} and \type{s}.}
-%D They are \writestatus{dummy}{demo}\color[yellow]{stacked}.
-%D
-%D \egroup
-
-\newif\ifimmediatewrite
-
-\ifx\eTeXversion\undefined
-
- \let\showwhatsits \relax
- \let\dontshowwhatsits\relax
-
-\else
-
- \let\supernormalmark \normalmark % mark may already been superseded
- \let\supernormalmarks \normalmarks % mark may already been superseded
-
- \def\showwhatsits
- {\protected\def\normalmark {\visualwhatsit100+m\supernormalmark }%
- \protected\def\normalmarks{\visualwhatsit100+m\supernormalmarks}%
- \protected\def\special {\visualwhatsit0100s\normalspecial }%
- \protected\def\write {\visualwhatsit001-w\normalwrite }%
- \let\immediate\immediatewhatsit
- \appendtoks\dontshowwhatsits\to\everystoptext}
-
- \def\immediatewhatsit
- {\bgroup\futurelet\next\doimmediatewhatsit}
-
- \def\doimmediatewhatsit
- {\ifx\next\write
- \egroup\immediatewritetrue
- \else
- \egroup\expandafter\normalimmediate
- \fi}
-
- \def\dontshowwhatsits
- {\let\immediate \normalimmediate
- \let\normalmark\supernormalmark
- \let\special \normalspecial
- \let\write \normalwrite}
-
- \def\visualwhatsit#1#2#3#4#5%
- {\bgroup
- \pushwhatsit
- \dontinterfere
- \dontcomplain
- \dontshowcomposition
- \dontshowwhatsits
- \ttx
- \ifvmode\donetrue\else\donefalse\fi
- \setbox\scratchbox\hbox
- {\ifdone
- \colored[r=#1,g=#2,b=#3]{#5}% temp hack
- \else
- \colored[s=0]{#5}% temp hack
- \fi}%
- \setbox\scratchbox\hbox
- {\ifdone
- \colored[r=#1,g=#2,b=#3]{\vrule\!!width\wd\scratchbox}% temp hack
- \else
- \colored[s=0]{\vrule\!!width\wd\scratchbox}% temp hack
- \fi
- \hskip-\wd\scratchbox\box\scratchbox}%
- \scratchdimen1ex
- \setbox\scratchbox\hbox
- {\ifdone\hskip\else\raise#4\fi\scratchdimen\box\scratchbox}%
- \smashbox\scratchbox
- \ifdone\nointerlineskip\fi
- \box\scratchbox
- \ifvmode\nointerlineskip\fi
- \popwhatsit
- \egroup
- \ifimmediatewrite
- \immediatewritefalse
- \expandafter\normalimmediate
- \fi}
-
- \def\pushwhatsit
- {\ifzeropt\lastskip
- \ifcase\lastpenalty
- \ifzeropt\lastkern
- \ifhmode
- \let\popwhatsit\relax
- \else
- \edef\popwhatsit{\prevdepth\the\prevdepth}%
- \fi
- \else
- \ifhmode
- \edef\popwhatsit{\kern\the\lastkern}\unkern
- \else
- \edef\popwhatsit{\kern\the\lastkern\prevdepth\the\prevdepth}%
- \kern-\lastkern
- \fi
- \fi
- \else
- \ifhmode
- \edef\popwhatsit{\the\lastpenalty}%
- \unpenalty
- \else
- \edef\popwhatsit{\penalty\the\lastpenalty\prevdepth\the\prevdepth}%
- %\nobreak
- \fi
- \fi
- \else
- \ifhmode
- \edef\popwhatsit{\hskip\the\lastskip}\unskip
- \else
- \edef\popwhatsit{\vskip\the\lastskip\prevdepth\the\prevdepth}%
- \vskip-\lastskip
- \fi
- \fi}
-
-\fi
-
-%D The next macro can be used to keep track of classes of
-%D boxes (handy for development cq.\ tracing).
-
-\def\dodotagbox#1#2#3% can be reimplemented
- {\def\next##1##2##3##4%
- {\vbox to \ht#2{##3\hbox to \wd#2{##1#3##2}##4}}%
- \processaction
- [#1]
- [ l=>\next\relax\hfill\vfill\vfill,
- r=>\next\hfill\relax\vfill\vfill,
- t=>\next\hfill\hfill\relax\vfill,
- b=>\next\hfill\hfill\vfill\relax,
- lt=>\next\relax\hfill\relax\vfill,
- lb=>\next\relax\hfill\vfill\relax,
- rt=>\next\hfill\relax\relax\vfill,
- rb=>\next\hfill\relax\vfill\relax,
- tl=>\next\relax\hfill\relax\vfill,
- bl=>\next\relax\hfill\vfill\relax,
- tr=>\next\hfill\relax\relax\vfill,
- br=>\next\hfill\relax\vfill\relax,
- \s!default=>\next\hfill\hfill\vfill\vfill,
- \s!unknown=>\next\hfill\hfill\vfill\vfill]}
-
-\def\dotagbox[#1]#2%
- {\bgroup
- \dowithnextbox
- {\setbox\scratchbox\flushnextbox
- \setbox\nextbox\ifhbox\nextbox\hbox\else\vbox\fi
- \bgroup
- \startoverlay
- {\copy\scratchbox}
- {\dodotagbox{#1}\scratchbox{\framed
- [\c!background=\v!screen,\c!backgroundscreen=1]{#2}}}
- \stopoverlay
- \egroup
- \nextboxwd\the\wd\scratchbox
- \nextboxht\the\ht\scratchbox
- \nextboxdp\the\dp\scratchbox
- \flushnextbox
- \egroup}}
-
-\def\tagbox
- {\dosingleempty\dotagbox}
-
-%D \macros
-%D {coloredhbox,coloredvbox,coloredvtop,
-%D coloredstrut}
+%D Possible values are: \type {fontkern}, \type {kern}, \type {glue}, \type
+%D {penalty}, \type {hbox}, \type {vbox}, \type {all}, \type {reset}, \type
+%D {makeup}, \type {whatsit}, \type{glyph}.
%D
-%D The following visualizations are used in some of the manuals:
+%D In due time some special visualzation of math will move here as well.
-\definecolor[boxcolor:ht][r=.5,g=.75,b=.5]
-\definecolor[boxcolor:dp][r=.5,g=.5,b=.75]
-\definecolor[boxcolor:wd][r=.75,g=.5,b=.5]
-\definecolor[strutcolor] [r=.5,g=.25,b=.25]
+\writestatus{loading}{ConTeXt Tracing Macros / Visualization}
-\def\coloredbox#1%
- {\dowithnextbox{#1{\hbox
- {\blackrule[\c!width=\nextboxwd,\c!height=\nextboxht,\c!depth=\zeropoint,\c!color=boxcolor:ht]%
- \hskip-\nextboxwd
- \blackrule[\c!width=\nextboxwd,\c!height=\zeropoint,\c!depth=\nextboxdp,\c!color=boxcolor:dp]%
- \hskip-\nextboxwd
- \box\nextbox}}}#1}
+\registerctxluafile{trac-vis}{1.001}
-\def\coloredhbox{\coloredbox\hbox}
-\def\coloredvbox{\coloredbox\vbox}
-\def\coloredvtop{\coloredbox\vtop}
+\unprotect
-\def\coloredstrut
- {\color[strutcolor]{\def\strutwidth{2\points}\setstrut\strut}}
+\definesystemattribute[visual][public,global]
+
+%D We only provide box visualizers as they can come in handy for testing
+%D macros. In due time we will move some of the m-visual code here too.
+
+\let\syst_visualizers_hbox\hbox
+\let\syst_visualizers_vbox\vbox
+\let\syst_visualizers_vtop\vtop
+
+\unexpanded\def\ruledhbox{\syst_visualizers_hbox attr \visualattribute \ctxcommand{visual("simplehbox")} }
+\unexpanded\def\ruledvbox{\syst_visualizers_vbox attr \visualattribute \ctxcommand{visual("simplevbox")} }
+\unexpanded\def\ruledvtop{\syst_visualizers_vtop attr \visualattribute \ctxcommand{visual("simplevtop")} } % special case
+\unexpanded\def\ruledtopv{\syst_visualizers_vtop attr \visualattribute \ctxcommand{visual("vtop")} }
+
+\unexpanded\def\showmakeup
+ {\ctxcommand{setvisual("makeup")}%
+ \let\normalvtop\ruledtopv
+ \let\vtop \ruledtopv}
+
+\unexpanded\def\showallmakeup
+ {\ctxcommand{setvisual("all")}%
+ \let\normalvtop\ruledtopv
+ \let\vtop \ruledtopv
+ \showstruts}
+
+\unexpanded\def\showboxes
+ {\ctxcommand{setvisual("boxes")}%
+ \let\normalvtop\ruledtopv
+ \let\vtop \ruledtopv}
+
+\unexpanded\def\showglyphs
+ {\ctxcommand{setvisual("glyph")}}
+
+\unexpanded\def\showfontkerns
+ {\ctxcommand{setvisual("fontkern")}}
+
+\unexpanded\def\setvisualizerfont
+ {\dosingleempty\syst_visualizers_setfont}
+
+\def\syst_visualizers_setfont[#1]% somename at 4pt
+ {\begingroup
+ \doifelsenothing{#1}{\definedfont[Mono at 4pt]}{\definedfont[#1]}%
+ \ctxlua{nodes.visualizers.setfont()}%
+ \endgroup}
+
+%D Overload:
+
+% \def\spac_struts_vide_hbox
+% {\hbox attr \visualattribute \ctxcommand{visual("strut")} }
+
+\def\spac_struts_vide_hbox
+ {\edef\spac_struts_vide_hbox{\hbox attr \visualattribute \ctxcommand{visual("strut")} }%
+ \spac_struts_vide_hbox}
+
+%D We keep this one:
+
+\unexpanded\def\dontinterfere
+ {\reseteverypar
+ \parindent\zeropoint
+ \parskip \zeropoint
+ \leftskip \zeropoint
+ \rightskip\zeropoint
+ \relax}
+
+%D We keep these for a while:
+
+\let\ruledvcenter \vcenter
+\let\ruledhss \hss
+\let\ruledhfil \hfil
+\let\ruledhfill \hfill
+\let\ruledhfilll \hfilll
+\let\ruledhfilneg \hfilneg
+\let\ruledhfillneg \hfillneg
+\let\ruledhfilllneg \hfilllneg
+\let\ruledvss \vss
+\let\ruledvfil \vfil
+\let\ruledvfill \vfill
+\let\ruledvfilll \vfilll
+\let\ruledvfilneg \vfilneg
+\let\ruledvfillneg \vfillneg
+\let\ruledvfilllneg \vfilllneg
+\let\ruledhskip \hskip
+\let\ruledvskip \vskip
+\let\ruledkern \kern
+\let\ruledhglue \hglue
+\let\ruledvglue \vglue
+\let\ruledmkern \mkern
+\let\ruledmskip \mskip
+\let\ruledpenalty \penalty
\protect \endinput
diff --git a/tex/context/base/type-imp-husayni.mkiv b/tex/context/base/type-imp-husayni.mkiv
index b3c1af5b7..b81996c33 100644
--- a/tex/context/base/type-imp-husayni.mkiv
+++ b/tex/context/base/type-imp-husayni.mkiv
@@ -1,137 +1,144 @@
-\definefontfeature
+%D \module
+%D [ file=type-imp-husayni,
+%D version=2008.08.08, % or whatever ... onwards
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Husayni,
+%D author=Idris Samawi Hamid \& Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D For a detailed list of features and names, see husayni.lfg. In fact, the following
+%D sets will go there.
+
+\definefontfeature
[husayni-default]
- [analyze=yes,mode=node,
- language=dflt,script=arab,
- ccmp=yes, % adds identity dots to unicode letters; includes dynamic dot placement
- init=yes,medi=yes,fina=yes, % contextual analysis
- % dlig=yes, % Hamzahbelow under YaaHamzahabove
- rlig=yes, % indispensable
- calt=yes, % ayah+numerals
- salt=yes, % includes manual justification with Tatwiil
- % fchr=yes % formatting chars
- anum=yes, % replace latin numerals with arabic-script ones
- ss01=yes, % Allah, Muhammad,
- % ss02=yes, % ss01 + Allah_final
- ss03=yes, % level-1 stack over Jiim, initial entry only
- % ss04=yes, % level-1 stack over Jiim, initial/medial entry
- % ss05=yes, % multi-level Jiim stacking, initial/medial entry
- % ss06=yes, % aesthetic Faa/Qaaf for FJ_mm, FJ_mf connection
- ss07=yes, % initial-entry stacking over Haa
- % ss08=yes, % initial/medial stacking over Haa, minus HM_mf strings
- % ss09=yes, % initial/medial Haa stacking plus HM_mf strings
- ss10=yes, % basic dipped Miim, initial-entry B_S-stack over Miim
- % ss11=yes, % full dipped Miim, initial-entry B_S-stack over Miim
- ss12=yes, % XBM_im initial-medial entry B_S-stack over Miim,
- % ss13=yes, % full initial-medial entry B_S-stacked Miim
- % ss14=yes, initial entry, stacked Laam on Miim
- ss15=yes, % full stacked Laam-on-Miim
- ss16=yes, % initial entry, stacked Ayn-on-Miim
- % ss17=yes, % full stacked Ayn-on-Miim
- % ss18=yes, % LMJ_im % already contained in ss03--05, may remove
- ss19=yes, % LM_im
- % ss20=yes, % KLM_m, sloped Miim
- % ss21=yes, % KLM_i_mm/LM_mm, sloped Miim
- % ss22=yes, % filled sloped Miim
- % ss23=yes, % LM_mm, non-sloped Miim
- ss24=yes, % BR_i_mf, BN_i_mf
- ss25=yes, % basic LH_im % might merge with ss24
- ss26=yes, % full Yaa.final special strings: BY_if, BY_mf, LY_mf
- ss27=yes, % basic thin Miim.final
- % ss28=yes, % full thin Miim.final % to be moved to jsnn
- % ss29=yes, % basic short Miim.final
- % ss30=yes, % full short Miim.final % to be moved to jsnn
- ss31=yes, % basic Raa.final strings: JR and SR
- % ss32=yes, % basic Raa.final strings: JR, SR, and BR
- % ss33=yes, % TtR % to be moved to jsnn
- ss34=yes, % AyR style % also available in jsnn
- ss35=yes, % full Kaaf contexts
- ss36=yes, % full Laam contexts
- ss37=yes, % Miim-Miim contexts
- ss38=yes, % basic dipped Haa, B_SH_mm
- % ss39=yes, % full dipped Haa, B_S_LH_i_mm_Mf
- % ss40=yes, % aesthetic dipped medial Haa
- ss41=yes, % high and low Baa strings
- ss42=yes, % diagonal entry
- ss43=yes, % initial alternates
- % ss44=yes, % hooked final alif
- % ss45=yes, % BMA_f
- % ss46=yes, % BM_mm_alt, for JBM combinations
- % ss47=yes, % Shaddah-<kasrah> combo
- % ss48=yes, % Auto-sukuun
- % ss49=yes, % No vowels
- % ss50=yes, % Shaddah/MaaddahHamzah only
- % ss51=yes, % No Skuun
- % ss52=yes, % No Waslah
- % ss53=yes, % No Waslah
- % ss54=yes, % chopped finals
- % ss55=yes, % idgham-tanwin
- ss60=yes, %
- % js01=yes, % Raawide
- % js02=yes, % Yaawide
- % js03=yes, % Kaafwide
- % js04=yes, % Nuunwide
- % js05=yes, % Kaafwide Nuunwide Siinwide Baawide
- % js06=yes, % final Haa wide
- % js07=yes, % thin Miim
- % js08=yes, % short Miim
- % js09=yes, % wide Siin
- % js10=yes, % thuluth-style initial Haa, final Miim, MRw_mf
- % js11=yes, % level-1 stretching
- % js12=yes, % level-2 stretching
- % js13=yes, % level-3 stretching
- % js14=yes, % final Alif
- % js15=yes, % hooked final Alif
- js16=yes, % aesthetic medial Faa/Qaaf
- % js17=yes, % fancy isol Haa after Daal, Raa, and Waaw
- % js18=yes, % Laamwide, alternate substitution
- % js19=yes, % level-4 stretching, only siin and Hhaa for basmalah
- % js20=yes, % level-5 stretching, only siin and Hhaa for basmalah
- % js21=yes, % Haa.final_alt2
- % calt=yes, % to be used for vowel/dot-based dynamics
- % ttwl=yes, % for simple, horizontal stretching, not yet implemented in luatex/mkiv
- % flts=yes, % Final Glyph On Line Alternates Short: Baa-like
- % fltw=yes, % Final Glyph On Line Alternates Wide: Baa-like
- % gclr=yes, % Geometric Cursive LR : for testing GPOS only!
- % gcrl=yes, % Geometric Cursive RL
- % gklr=yes, % Geometric Kerning LR
- % gkrl=yes, % Geometric Kerning RL
- kern=yes, % includes kerning of dot-base pairs, and final pairs in continuous strings
- curs=yes, % we don't curs final pairs, padj for that
- mark=yes, % vowels
- mkmk=yes, % stacked vowels
+ [analyze=yes,
+ mode=node,
+ language=dflt,
+ script=arab,
+ ccmp=yes, % adds identity dots to unicode letters; includes dynamic dot placement
+ init=yes, % contextual analysis
+ medi=yes, % contextual analysis
+ fina=yes, % contextual analysis
+ rlig=yes, % indispensable
+ calt=yes, % ayah+numerals
+ salt=yes, % includes manual justification with Tatwiil
+ anum=yes, % replace latin numerals with arabic-script ones
+ ss01=yes, % Allah, Muhammad,
+ ss03=yes, % level-1 stack over Jiim, initial entry only
+ ss10=yes, % basic dipped Miim, initial-entry B_S-stack over Miim
+ ss12=yes, % XBM_im initial-medial entry B_S-stack over Miim,
+ ss15=yes, % full stacked Laam-on-Miim
+ ss16=yes, % initial entry, stacked Ayn-on-Miim
+ ss19=yes, % LM_im
+ ss24=yes, % BR_i_mf, BN_i_mf
+ ss25=yes, % basic LH_im % might merge with ss24
+ ss26=yes, % full Yaa.final special strings: BY_if, BY_mf, LY_mf
+ ss27=yes, % basic thin Miim.final
+ ss31=yes, % basic Raa.final strings: JR and SR
+ ss34=yes, % AyR style % also available in jsnn
+ ss35=yes, % full Kaaf contexts
+ ss36=yes, % full Laam contexts
+ ss37=yes, % Miim-Miim contexts
+ ss38=yes, % basic dipped Haa, B_SH_mm
+ ss41=yes, % high and low Baa strings
+ ss42=yes, % diagonal entry
+ ss43=yes, % initial alternates
+ ss60=yes, %
+ js16=yes, % aesthetic medial Faa/Qaaf
+ kern=yes, % includes kerning of dot-base pairs, and final pairs in continuous strings
+ curs=yes, % we don't curs final pairs, padj for that
+ mark=yes, % vowels
+ mkmk=yes, % stacked vowels
tlig=yes,
- colorscheme=husayni:default]
+ goodies=husayni,
+ colorscheme=default]
+
+\definefontfeature
+ [husayni-alternative] % was husayni-default2
+ [analyze=yes,
+ mode=node,
+ language=dflt,
+ script=arab,
+ ccmp=yes, % adds identity dots to unicode letters; includes dynamic dot placement
+ init=yes, % contextual analysis
+ medi=yes, % contextual analysis
+ fina=yes, % contextual analysis
+ rlig=yes, % indispensable
+ calt=yes, % ayah+numerals
+ salt=yes, % includes manual justification with Tatwiil
+ anum=yes, % replace latin numerals with arabic-script ones
+ ss01=yes, % Allah, Muhammad,
+ ss03=yes, % level-1 stack over Jiim, initial entry only
+ ss10=yes, % basic dipped Miim, initial-entry B_S-stack over Miim
+ ss12=yes, % XBM_im initial-medial entry B_S-stack over Miim,
+ ss15=yes, % full stacked Laam-on-Miim
+ ss16=yes, % initial entry, stacked Ayn-on-Miim
+ ss19=yes, % LM_im
+ ss24=yes, % BR_i_mf, BN_i_mf
+ ss25=yes, % basic LH_im % might merge with ss24
+ ss26=yes, % full Yaa.final special strings: BY_if, BY_mf, LY_mf
+ ss27=yes, % basic thin Miim.final
+ ss31=yes, % basic Raa.final strings: JR and SR
+ ss34=yes, % AyR style % also available in jsnn
+ ss35=yes, % full Kaaf contexts
+ ss36=yes, % full Laam contexts
+ ss37=yes, % Miim-Miim contexts
+ ss38=yes, % basic dipped Haa, B_SH_mm
+ ss41=yes, % high and low Baa strings
+ ss42=yes, % diagonal entry
+ ss43=yes, % initial alternates
+ ss60=yes, %
+ js16=yes, % aesthetic medial Faa/Qaaf
+ kern=yes, % includes kerning of dot-base pairs, and final pairs in continuous strings
+ curs=yes, % we don't curs final pairs, padj for that
+ mark=yes, % vowels
+ mkmk=yes, % stacked vowels
+ tlig=yes]
\definefontfeature
[husayni-tt]
- [analyze=yes,mode=node,
- language=dflt,script=arab,
- ccmp=yes, % adds identity dots to unicode letters; includes dynamic dot placement
- init=yes,medi=yes,fina=yes, % contextual analysis
- rlig=yes, % indispensable
+ [analyze=yes,
+ mode=node,
+ language=dflt,
+ script=arab,
+ ccmp=yes,
+ init=yes,
+ medi=yes,
+ fina=yes,
+ rlig=yes,
fchr=yes,
- kern=yes, % includes kerning of dot-base pairs, and final pairs in continuous strings
- curs=yes, % we don't curs final pairs, padj for that
- mark=yes, % vowels
- mkmk=yes] % stacked vowels
+ kern=yes,
+ curs=yes,
+ mark=yes,
+ mkmk=yes]
\definefontfeature
[husayni-mono]
- [analyze=yes,mode=node,
- language=dflt,script=arab,ccmp=no,
- init=yes,medi=yes,fina=yes,isol=yes,
- rlig=yes,liga=yes,
+ [analyze=yes,
+ mode=node,
+ language=dflt,
+ script=arab,
+ ccmp=no,
+ init=yes,
+ medi=yes,
+ fina=yes,
+ isol=yes,
mset=yes]
-
+
\definedelimitedtext
[ornatequote]
[left={‏\char"FD3F\penalty10000},
- right={‏\char"FD3E\penalty10000}]
-
+ right={‏\char"FD3E\penalty10000}]
+
\definedelimitedtext
[arparenthesis]
[left={‏\char"0028},
- right={‏\char"0029}]
+ right={‏\char"0029}]
\definedelimitedtext
[arquotation]
@@ -143,4 +150,49 @@
[arquote]
[left={‏\symbol[rightquote]},
right={‏\symbol[leftquote]},
- leftmargin=standard] \ No newline at end of file
+ leftmargin=standard]
+
+\definebodyfontenvironment
+ [husayni-default]
+ [default]
+ [interlinespace=4.4ex]
+
+\definefontfallback
+ [husayni-latin]
+ [file:lmroman12-regular*default]
+ [basiclatin,latin-1supplement,latinextended-A,latinextendedadditional]
+ [force=no,
+ rscale=.7]
+
+\definefontfallback
+ [husayni-mono]
+ [file:cour*husayni-mono]
+ [arabic,arabicpresentationformsa,arabicpresentationformsb,arabicsupplement,0x200C,0x200D,0x200E,0x200F]
+ % [force=no]
+
+\definebodyfontenvironment[20.7pt]
+\definebodyfontenvironment[24.8pt]
+\definebodyfontenvironment[29.8pt]
+\definebodyfontenvironment[35.8pt]
+
+\starttypescriptcollection[husayni]
+
+ \starttypescript [naskh] [husayni] [name]
+ \definefontsynonym [Arabic-Light] [name:husayni] [goodies=husayni,features=husayni-default]
+ \definefontsynonym [Arabic-Bold] [name:husayni] [goodies=husayni,features=husayni-default]
+ \definefontsynonym [Arabic-Italic] [name:husayni] [goodies=husayni,features=husayni-default]
+ \definefontsynonym [Arabic-Bold-Italic] [name:husayni] [goodies=husayni,features=husayni-default]
+
+ \definefontsynonym [Serif] [Arabic-Light]
+ \definefontsynonym [SerifItalic] [Arabic-Italic]
+ \definefontsynonym [SerifBold] [Arabic-Bold]
+ \definefontsynonym [SerifBoldItalic] [Arabic-Bold-Italic]
+ \stoptypescript
+
+ \starttypescript [husayni-default]
+ \definetypeface [husayni-default] [rm] [naskh] [husayni] [default] [fallbacks=husayni-latin]
+ \definetypeface [husayni-default] [tt] [mono] [modern] [default] [fallbacks=husayni-latin]
+ \definetypeface [husayni-default] [mm] [math] [xitsbidi] [default]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/tex/context/base/type-ini.lua b/tex/context/base/type-ini.lua
index 4ce953168..758fb5683 100644
--- a/tex/context/base/type-ini.lua
+++ b/tex/context/base/type-ini.lua
@@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['type-ini'] = {
-- more code will move here
+local commands, context = commands, context
+
local gsub = string.gsub
local report_typescripts = logs.reporter("fonts","typescripts")
@@ -15,13 +17,14 @@ local report_typescripts = logs.reporter("fonts","typescripts")
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()
+ -- context.startreadingfile()
+ -- context.pushendofline()
+ -- context.unprotect()
+ -- context.input(foundname)
+ -- context.protect()
+ -- context.popendofline()
+ -- context.stopreadingfile()
+ context.loadfoundtypescriptfile(foundname)
end
local name_one, name_two
diff --git a/tex/context/base/type-ini.mkvi b/tex/context/base/type-ini.mkvi
index 8ca42854f..8345a97f9 100644
--- a/tex/context/base/type-ini.mkvi
+++ b/tex/context/base/type-ini.mkvi
@@ -27,6 +27,8 @@
\unprotect
+\definesystemvariable {ts} % TypeScript / for the moment we keep this one
+
\newcount \c_font_typescripts_n_of_preloaded
\newconditional\c_font_typescripts_quit
\newtoks \c_font_typescripts_document
@@ -134,15 +136,21 @@
% 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\loadfoundtypescriptfile#1%
+ {\startreadingfile
+ \pushendofline
+ \unprotect
+ \input{#1}%
+ \protect
+ \popendofline
+ \stopreadingfile}
+
\unexpanded\def\quittypescriptscanning
{\settrue\c_font_typescripts_quit} % public
diff --git a/tex/context/base/node-par.lua b/tex/context/base/typo-bld.lua
index 8eafd1f6e..87d280541 100644
--- a/tex/context/base/node-par.lua
+++ b/tex/context/base/typo-bld.lua
@@ -1,11 +1,13 @@
-if not modules then modules = { } end modules ['node-par'] = {
+if not modules then modules = { } end modules ['typo-bld'] = { -- was node-par
version = 1.001,
- comment = "companion to node-par.mkiv",
+ comment = "companion to typo-bld.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
+local insert, remove = table.insert, table.remove
+
local builders, nodes, node = builders, nodes, node
builders.paragraphs = builders.paragraphs or { }
@@ -23,10 +25,20 @@ local numbers = constructors.numbers
constructors.methods = constructors.methods or { }
local methods = constructors.methods
-local p_attribute = attributes.numbers['parbuilder'] or 999
-constructors.attribute = p_attribute
+local a_parbuilder = attributes.numbers['parbuilder'] or 999 -- why 999
+constructors.attribute = a_parbuilder
+local unsetvalue = attributes.unsetvalue
+local texsetattribute = tex.setattribute
local has_attribute = node.has_attribute
+local texnest = tex.nest
+
+local nodepool = nodes.pool
+local new_baselineskip = nodepool.baselineskip
+local new_lineskip = nodepool.lineskip
+local insert_node_before = node.insert_before
+local hpack_node = node.hpack
+
local starttiming = statistics.starttiming
local stoptiming = statistics.stoptiming
@@ -36,14 +48,46 @@ storage.register("builders/paragraphs/constructors/numbers", numbers, "builders.
local report_parbuilders = logs.reporter("parbuilders")
local mainconstructor = nil -- not stored in format
+local nofconstructors = 0
+local stack = { }
+
+function constructors.define(name)
+ nofconstructors = nofconstructors + 1
+ names[nofconstructors] = name
+ numbers[name] = nofconstructors
+end
+
+function constructors.set(name) --- will go
+ if name then
+ mainconstructor = numbers[name] or unsetvalue
+ else
+ mainconstructor = stack[#stack] or unsetvalue
+ end
+ texsetattribute(a_parbuilder,mainconstructor)
+ if mainconstructor ~= unsetvalue then
+ constructors.enable()
+ end
+end
-function constructors.register(name,number)
- names[number] = name
- numbers[name] = number
+function constructors.start(name)
+ local number = numbers[name]
+ insert(stack,number)
+ mainconstructor = number or unsetvalue
+ texsetattribute(a_parbuilder,mainconstructor)
+ if mainconstructor ~= unsetvalue then
+ constructors.enable()
+ end
+-- report_parbuilders("start %s",name)
end
-function constructors.set(name)
- mainconstructor = numbers[name]
+function constructors.stop()
+ remove(stack)
+ mainconstructor = stack[#stack] or unsetvalue
+ texsetattribute(a_parbuilder,mainconstructor)
+ if mainconstructor == unsetvalue then
+ constructors.disable()
+ end
+-- report_parbuilders("stop")
end
-- return values:
@@ -56,7 +100,7 @@ function constructors.handler(head,followed_by_display)
if type(head) == "boolean" then
return head
else
- local attribute = has_attribute(head,p_attribute) or mainconstructor
+ local attribute = has_attribute(head,a_parbuilder) -- or mainconstructor
if attribute then
local method = names[attribute]
if method then
@@ -79,10 +123,20 @@ function constructors.methods.default(head,followed_by_display)
return true -- let tex break
end
--- also for testing (no surrounding spacing done)
-
-function constructors.methods.oneline(head,followed_by_display)
- return node.hpack(head)
+-- also for testing (now also surrounding spacing done)
+
+function builders.paragraphs.constructors.methods.oneline(head,followed_by_display)
+ -- when needed we will turn this into a helper
+ local t = texnest[texnest.ptr]
+ local h = hpack_node(head)
+ local d = tex.baselineskip.width - t.prevdepth - h.height
+ t.prevdepth = h.depth
+ t.prevgraf = 1
+ if d < tex.lineskiplimit then
+ return insert_node_before(h,h,new_lineskip(tex.lineskip))
+ else
+ return insert_node_before(h,h,new_baselineskip(d))
+ end
end
-- It makes no sense to have a sequence here as we already have
@@ -90,17 +144,13 @@ end
--
-- local actions = nodes.tasks.actions("parbuilders")
--
--- yet (maybe some day).
---
--- todo: enable one as main
+-- yet ... maybe some day.
local actions = constructors.handler
local enabled = false
-function constructors.enable () enabled = true end
-function constructors.disable() enabled = false end
-
local function processor(head,followed_by_display)
+ -- todo: not again in otr so we need to flag
if enabled then
starttiming(parbuilders)
local head = actions(head,followed_by_display)
@@ -111,8 +161,26 @@ local function processor(head,followed_by_display)
end
end
+function constructors.enable()
+ enabled = true
+end
+
+function constructors.disable()
+ enabled = false
+end
+
+
callbacks.register('linebreak_filter', processor, "breaking paragraps into lines")
statistics.register("linebreak processing time", function()
return statistics.elapsedseconds(parbuilders)
end)
+
+-- interface
+
+commands.defineparbuilder = constructors.define
+commands.startparbuilder = constructors.start
+commands.stopparbuilder = constructors.stop
+commands.setparbuilder = constructors.set
+commands.enableparbuilder = constructors.enable
+commands.disableparbuilder = constructors.disable
diff --git a/tex/context/base/typo-bld.mkiv b/tex/context/base/typo-bld.mkiv
new file mode 100644
index 000000000..10502005b
--- /dev/null
+++ b/tex/context/base/typo-bld.mkiv
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=typo-bld, % was node-par,
+%D version=2008.09.30,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Paragraph Building,
+%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 Node Macros / Paragraph Building}
+
+%D This is very experimental, undocumented, subjected to changes, etc. just as
+%D the underlying interfaces. But at least it's cleaned as part of the status-mkiv
+%D cleanup.
+
+% \startparbuilder[default]
+% \input tufte \par
+% \startparbuilder[oneline]
+% \input tufte \par
+% \stopparbuilder
+% \input tufte \par
+% \stopparbuilder
+%
+% \startparbuilder[oneline]
+% \dorecurse{100}{\input ward \par}
+% \stopparbuilder
+
+\unprotect
+
+\registerctxluafile{typo-bld}{1.001}
+
+\definesystemattribute[parbuilder][public]
+
+\installcorenamespace {parbuilder}
+
+\unexpanded\def\defineparbuilder[#1]%
+ {\ctxcommand{defineparbuilder("#1")}}
+
+\unexpanded\def\startparbuilder[#1]%
+ {\ifhmode\par\fi
+ \ctxcommand{startparbuilder("#1")}}
+
+\unexpanded\def\stopparbuilder
+ {\ifhmode\par\fi
+ \ctxcommand{stopparbuilder()}}
+
+\unexpanded\def\setmainparbuilder[#1]%
+ {\ctxcommand{setparbuilder("#1")}}
+
+% no high level interface, after all implementing a linebreaker is not something that
+% the average user will do
+
+\defineparbuilder[default] % just for testing
+\defineparbuilder[oneline] % just for testing
+\defineparbuilder[basic] % just for testing
+
+\def\enableparbuilders {\ctxcommand{enableparbuilder()}} % hooks in otr so we need to pickup
+\def\disableparbuilders{\ctxcommand{disableparbuilder()}} % hooks in otr so we need to pickup
+
+\protect \endinput
diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua
index 14f0b8b47..726518a85 100644
--- a/tex/context/base/typo-brk.lua
+++ b/tex/context/base/typo-brk.lua
@@ -29,7 +29,8 @@ local free_node = node.free
local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
local remove_node = nodes.remove -- ! nodes
-local link_nodes = nodes.link
+
+local tonodes = nodes.tonodes
local texattribute = tex.attribute
local unsetvalue = attributes.unsetvalue
@@ -139,10 +140,18 @@ methods[5] = function(head,start,settings) -- x => p q r
head, start, tmp = remove_node(head,start)
head, start = insert_node_before(head,start,new_disc())
local attr = tmp.attr
+ local font = tmp.font
start.attr = copy_nodelist(attr) -- todo: critical only
- start.pre = link_nodes(settings.right,tmp,attr)
- start.post = link_nodes(settings.left,tmp,attr)
- start.replace = link_nodes(settings.middle,tmp,attr)
+ local left, right, middle = settings.left, settings.right, settings.middle
+ if left then
+ start.pre = tonodes(tostring(left),font,attr) -- was right
+ end
+ if right then
+ start.post = tonodes(tostring(right),font,attr) -- was left
+ end
+ if middle then
+ start.replace = tonodes(tostring(middle),font,attr)
+ end
free_node(tmp)
insert_break(head,start,10000,10000)
end
diff --git a/tex/context/base/typo-brk.mkiv b/tex/context/base/typo-brk.mkiv
index 029f4402f..af498bfec 100644
--- a/tex/context/base/typo-brk.mkiv
+++ b/tex/context/base/typo-brk.mkiv
@@ -38,14 +38,14 @@
\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"
+ \getdummyparameters[\c!type=1,\c!nleft=3,\c!nright=3,\s!language=,\c!left=,\c!right=,\c!middle=,#3]%
+ \ctxcommand{definebreakpoint("#1", "#2", "\reallanguagetag{\directdummyparameter\s!language}", { % maybe deal with #3 at the lua end
+ type = \directdummyparameter\c!type,
+ nleft = "\directdummyparameter\c!nleft",
+ nright = "\directdummyparameter\c!nright",
+ right = "\directdummyparameter\c!right",
+ left = "\directdummyparameter\c!left",
+ middle = "\directdummyparameter\c!middle"
} )}%
\endgroup}
@@ -77,6 +77,8 @@
% \setbreakpoints[compound]
% \start \hsize 1mm test-test \par \stop
+%D Maybe some day default:
+%
% \setbreakpoints[compound]
\protect \endinput
diff --git a/tex/context/base/typo-cap.mkiv b/tex/context/base/typo-cap.mkiv
index 28ced7c42..25a0ff9ee 100644
--- a/tex/context/base/typo-cap.mkiv
+++ b/tex/context/base/typo-cap.mkiv
@@ -15,6 +15,9 @@
\unprotect
+%D Maybe we need a more clever system: either command or style mode etc. so
+%D that we can avoid the grouped mess in a simple style switch.
+
\registerctxluafile{typo-cap}{1.001}
\definesystemattribute[case][public]
@@ -146,6 +149,14 @@
\unexpanded\def\realSmallcapped {\groupedcommand{\sc\setcharactercasing[\v!Word ]}{}} % one upper + font
\unexpanded\def\realSmallCapped {\groupedcommand{\sc\setcharactercasing[\v!Words ]}{}} % some upper
+\unexpanded\def\font_style_pseudosmallcapped{\setcharactercasing [\v!WORD ]\signalcharacter\tx} % all upper
+\unexpanded\def\font_style_pseudoSmallcapped{\setcharactercasing [\v!capital]\signalcharacter\tx} % one upper + font
+\unexpanded\def\font_style_pseudoSmallCapped{\setcharactercasing [\v!Capital]\signalcharacter\tx} % some upper + font
+
+\unexpanded\def\font_style_realsmallcapped {\sc\setcharactercasing[\v!WORD ]} % all lower
+\unexpanded\def\font_style_realSmallcapped {\sc\setcharactercasing[\v!Word ]} % one upper + font
+\unexpanded\def\font_style_realSmallCapped {\sc\setcharactercasing[\v!Words ]} % some upper
+
\unexpanded\def\typo_capitals_smallcaps
{\ifconditional\c_typo_capitals_pseudo
\expandafter\firstoftwoarguments
@@ -157,6 +168,10 @@
\unexpanded\def\Smallcapped{\typo_capitals_smallcaps\pseudoSmallcapped\realSmallcapped}
\unexpanded\def\SmallCapped{\typo_capitals_smallcaps\pseudoSmallCapped\realSmallCapped}
+\unexpanded\def\font_style_smallcapped{\typo_capitals_smallcaps\font_style_pseudosmallcapped\font_style_realsmallcapped}
+\unexpanded\def\font_style_Smallcapped{\typo_capitals_smallcaps\font_style_pseudoSmallcapped\font_style_realSmallcapped}
+\unexpanded\def\font_style_SmallCapped{\typo_capitals_smallcaps\font_style_pseudoSmallCapped\font_style_realSmallCapped}
+
\unexpanded\def\autocap{\ifmmode\expandafter\normalcap\else\expandafter\smallcapped\fi}
\appendtoks
@@ -171,6 +186,10 @@
\let\normalWORD \WORD
\let\normalword \word
+\let\font_style_normalsmallcapped\font_style_smallcapped
+\let\font_style_normalWORD \WORD
+\let\font_style_normalword \word
+
%D As suggested by WS:
\unexpanded\def\notsmallcapped{\groupedcommand{\setcharactercasing[\v!word]\signalcharacter}{}}
@@ -183,21 +202,22 @@
%D
%D \showsetup{setupcapitals}
-\let\normalsmallcapped\smallcapped
+\installcorenamespace{capitals}
-\definesystemvariable{kk}
+\installsetuponlycommandhandler \??capitals {capitals}
-\unexpanded\def\setupcapitals
- {\dosingleempty\typo_capitals_setup}
+\let\normalsmallcapped\smallcapped
-\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 ]}%
- \doifelse\@@kksc\v!yes\userealcaps\usepseudocaps}
+\appendtoks
+ \doifelse{\directcapitalsparameter\c!title}\v!yes
+ {\definealternativestyle[\v!capital ][\font_style_normalsmallcapped][\font_style_normalsmallcapped]%
+ \definealternativestyle[\v!smallcaps][\sc][\sc]}
+ {\definealternativestyle[\v!capital ][\font_style_normalsmallcapped][\font_style_normalWORD]%
+ \definealternativestyle[\v!smallcaps][\sc][\font_style_normalWORD]}%
+ \doifelse{\directcapitalsparameter\s!sc}\v!yes
+ \userealcaps
+ \usepseudocaps
+\to \everysetupcapitals
\let\uppercased\normalWORD
\let\lowercased\normalword
diff --git a/tex/context/base/typo-del.mkiv b/tex/context/base/typo-del.mkiv
index b2213db65..7c36ef3c8 100644
--- a/tex/context/base/typo-del.mkiv
+++ b/tex/context/base/typo-del.mkiv
@@ -17,14 +17,19 @@
% THIS IS OBSOLETE:
-\unexpanded\def\setuphyphenmark
- {\dodoubleargument\getparameters[\??kp]}
+\installcorenamespace{hyphenmarksign} % let's not waste a setuphandler (yet)
\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}}
+ {\getdummyparameters[#1]%
+ \expandcheckedcsname\??hyphenmarksign{\dummyparameter\c!sign}\v!normal}
+
+\setvalue{\??hyphenmarksign\v!normal}%
+ {\let\textmodehyphen\normalhyphen
+ \let\textmodehyphendiscretionary\normalhyphendiscretionary}
+
+\setvalue{\??hyphenmarksign\v!wide}%
+ {\let\textmodehyphen\composedhyphen
+ \let\textmodehyphendiscretionary\composedhyphendiscretionary}
\setuphyphenmark[\c!sign=\v!wide]
@@ -32,19 +37,19 @@
\definesymbol[\c!righthyphen] [\languageparameter\c!righthyphen]
\definesymbol[\c!hyphen] [\languageparameter\c!hyphen]
-\def\normalhyphen
+\unexpanded\def\normalhyphen
{\hbox{\directsymbol\empty\c!hyphen}}
-\def\composedhyphen
+\unexpanded\def\composedhyphen
{\hbox{\directsymbol\empty\c!compoundhyphen}}
-\def\normalhyphendiscretionary
+\unexpanded\def\normalhyphendiscretionary
{\discretionary
{\hbox{\directsymbol\empty\c!righthyphen}}
{\hbox{\directsymbol\empty\c!lefthyphen}}
{\hbox{\directsymbol\empty\c!hyphen}}}
-\def\composedhyphendiscretionary
+\unexpanded\def\composedhyphendiscretionary
{\discretionary
{\hbox{\directsymbol\empty\c!rightcompoundhyphen}}
{\hbox{\directsymbol\empty\c!leftcompoundhyphen}}
@@ -219,8 +224,10 @@
[\c!middlespeech]
[\leftboundarycharacter\c!middlespeech{speech}]
-\appendtoks\def\quotation#1{"#1"}\to\simplifiedcommands
-\appendtoks\def\quote #1{'#1'}\to\simplifiedcommands
+\appendtoks
+ \def\quotation#1{"#1"}%
+ \def\quote #1{'#1'}%
+\to \everysimplifycommands
%D The next features was so desperately needed by Giuseppe
%D Bilotta that he made a module for it. Since this is a
diff --git a/tex/context/base/typo-dir.lua b/tex/context/base/typo-dir.lua
index 620862e85..13c0aec97 100644
--- a/tex/context/base/typo-dir.lua
+++ b/tex/context/base/typo-dir.lua
@@ -276,7 +276,7 @@ function directions.process(namespace,attribute,start) -- todo: make faster
end
end
elseif d == "l" or d == "en" then -- european number
- if autodir <= 0 then
+ if autodir <= 0 then -- could be option
force_auto_left_before()
end
elseif d == "r" or d == "al" then -- arabic number
@@ -285,9 +285,11 @@ function directions.process(namespace,attribute,start) -- todo: make faster
end
elseif d == "an" then -- arabic number
-- actually this is language dependent ...
- if autodir <= 0 then
---~ force_auto_right_before()
- force_auto_left_before()
+-- if autodir <= 0 then
+-- force_auto_left_before()
+-- end
+ if autodir >= 0 then
+ force_auto_right_before()
end
elseif d == "lro" then -- Left-to-Right Override -> right becomes left
if trace_directions then
diff --git a/tex/context/base/typo-itm.mkiv b/tex/context/base/typo-itm.mkiv
new file mode 100644
index 000000000..eb47e4076
--- /dev/null
+++ b/tex/context/base/typo-itm.mkiv
@@ -0,0 +1,273 @@
+%D \module
+%D [ file=typo-itm, % comes from core-mis
+%D version=2012.06.28,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Item 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 Node Macros / Item Lists}
+
+\unprotect
+
+%D This is a real old mechanism that we once used for questionaries. As it is documented
+%D we keep it around. A more modern implementation would probably use another approach
+%D but I don't want to spend too much time on it now. There are a couple of changes:
+%D
+%D \startitemize
+%D \startitem textwidth sets the combined width \stopitem
+%D \startitem width sets the symbolwidth \stopitem
+%D \startitem alternative is used instead of location \stopitem
+%D \stopitemize
+%D
+%D \startbuffer
+%D \items[alternative=left]{a,b,c}
+%D \items[alternative=left,align=middle,textalign=flushright,distance=1em]{a,b,c}
+%D \items[alternative=right]{a,b,c}
+%D \items[alternative=inmargin]{a,b,c}
+%D \items[alternative=top]{a,b,c}
+%D \items[alternative=bottom]{a,b,c}
+%D \items[alternative=bottom,align=flushleft,textstyle=bold,color=red,textcolor=green]{a,b,c}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This renders as:
+%D
+%D \getbuffer
+
+\installcorenamespace{items}
+\installcorenamespace{itemsalternatives}
+\installcorenamespace{itemshorizontal}
+\installcorenamespace{itemsvertical}
+
+\installcommandhandler \??items {items} \??items
+
+\setupitems
+ [\c!alternative=\v!left,
+ \c!symbol=5,
+ \c!textwidth=\availablehsize,
+ \c!align=\v!middle,
+ \c!textalign=\v!flushleft,
+ \c!distance=\zeropoint,
+ %\c!n=,
+ \c!before=\blank,
+ \c!inbetween={\blank[\v!medium]},
+ \c!after=\blank]
+
+\unexpanded\def\items
+ {\dosingleempty\typo_items_process}
+
+\newcount\c_typo_items_n
+\newcount\c_typo_items_m
+\newdimen\d_typo_items_text_width
+\newdimen\d_typo_items_symbol_width
+\newdimen\d_typo_items_distance
+\newbox \b_typo_items_symbols
+\newbox \b_typo_items_texts
+
+\def\typo_items_process[#1]#2%
+ {\bgroup
+ \setupitems[#1]%
+ \edef\p_typo_items_alternative{\itemsparameter\c!alternative}%
+ \ifcsname\??itemsalternatives\p_typo_items_alternative\endcsname \else
+ \let\p_typo_items_alternative\v!left
+ \fi
+ \let\currentitems\p_typo_items_alternative
+ \setupcurrentitems[#1]%
+ %
+ \edef\p_typo_items_textwidth{\itemsparameter\c!textwidth}%
+ \ifx\p_typo_items_textwidth\empty
+ \d_typo_items_text_width\availablehsize
+ \else
+ \d_typo_items_text_width\p_typo_items_textwidth\relax
+ \fi
+ %
+ \edef\p_typo_items_width{\itemsparameter\c!width}%
+ \ifx\p_typo_items_width\empty
+ \d_typo_items_symbol_width1.5\emwidth
+ \else
+ \d_typo_items_symbol_width\p_typo_items_width\relax
+ \fi
+ %
+ \edef\p_typo_items_distance{\itemsparameter\c!distance}%
+ \ifx\p_typo_items_distance\empty
+ \d_typo_items_distance\zeropoint
+ \else
+ \d_typo_items_distance\p_typo_items_distance\relax
+ \fi
+ %
+ \edef\p_typo_items_symbol{\itemsparameter\c!symbol}%
+ \ifx\p_typo_items_symbol\empty
+ \let\m_typo_items_symbol\firstofoneargument
+ \else\ifx\p_typo_items_symbol\v!none
+ \let\p_typo_items_symbol\empty
+ \let\m_typo_items_symbol\firstofoneargument
+ \else
+ \doifconversiondefinedelse\p_typo_items_symbol
+ {\def\m_typo_items_symbol{\convertnumber\p_typo_items_symbol}}
+ {\doifsymboldefinedelse\p_typo_items_symbol
+ {\def\m_typo_items_symbol{\symbol[\p_typo_items_symbol]\gobbleoneargument}}
+ {\let\m_typo_items_symbol\firstofoneargument}}%
+ \fi\fi
+ %
+ \edef\p_typo_items_align{\itemsparameter\c!align}%
+ \edef\p_typo_items_textalign{\itemsparameter\c!textalign}%
+ %
+ \edef\p_typo_items_n{\itemsparameter\c!n}%
+ \ifx\p_typo_items_n\empty
+ \getcommalistsize[#2]%
+ \c_typo_items_n\commalistsize\relax
+ \else
+ \c_typo_items_n\p_typo_items_n\relax
+ \fi
+ %
+ \parindent\zeropoint
+ \dontcomplain
+ %
+ \itemsparameter\c!before
+ \csname\??itemsalternatives\p_typo_items_alternative\endcsname{#2}%
+ \itemsparameter\c!after
+ \egroup}
+
+% rendering
+
+\setvalue{\??itemshorizontal\v!margin}#1%
+ {\ifnum\c_typo_items_m=\plusone\hss\else\hfill\fi
+ \strut#1%
+ \ifnum\c_typo_items_m=\c_typo_items_n\hss\else\hfill\fi}
+
+\setvalue{\??itemshorizontal\s!unknown}%
+ {\simplealignedbox\scratchwidth\m_typo_items_align}
+
+\def\typo_items_item_horizontal
+ {\advance\c_typo_items_m\plusone
+ \csname\??itemshorizontal
+ \ifcsname\??itemshorizontal\p_typo_items_align\endcsname
+ \p_typo_items_align
+ \else
+ \s!unknown
+ \fi
+ \endcsname}
+
+\setvalue{\??itemsvertical\s!unknown}%
+ {\simplealignedbox\scratchwidth\m_typo_items_align}
+
+\def\typo_items_item_vertical
+ {\advance\c_typo_items_m\plusone
+ \csname\??itemsvertical
+ \ifcsname\??itemsvertical\p_typo_items_align\endcsname
+ \p_typo_items_align
+ \else
+ \s!unknown
+ \fi
+ \endcsname}
+
+\def\typo_items_make_horizontal#1%
+ {\divide\scratchwidth\c_typo_items_n
+ \hbox{#1}}
+
+\def\typo_items_make_vertical#1%
+ {\vbox{#1}}
+
+\def\typo_items_construct_items_boxes#1%
+ {\setbox\b_typo_items_texts\hbox
+ {\c_typo_items_m\zerocount
+ \let\m_typo_items_align\p_typo_items_textalign
+ \scratchwidth\d_typo_items_text_width
+ \useitemsstyleandcolor\c!textstyle\c!textcolor
+ \typo_items_make{\processcommalist[#1]\typo_items_item}}%
+ \ifx\p_typo_items_symbol\empty
+ \setbox\b_typo_items_symbols\emptyhbox
+ \else
+ \setbox\b_typo_items_symbols\hbox
+ {\c_typo_items_m\zerocount
+ \let\m_typo_items_align\p_typo_items_align
+ \scratchwidth\d_typo_items_symbol_width
+ \useitemsstyleandcolor\c!style\c!color
+ \typo_items_make{\dorecurse\c_typo_items_n{\typo_items_item{\strut\m_typo_items_symbol\recurselevel}}}}%
+ \fi}
+
+% alternatives:
+
+\defineitems[\v!top][\c!width=\d_typo_items_text_width,\c!textalign=\itemsparameter\c!align]
+
+\setvalue{\??itemsalternatives\v!top}#1%
+ {\let\typo_items_make\typo_items_make_horizontal
+ \let\typo_items_item\typo_items_item_horizontal
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\vbox\bgroup
+ \forgetall
+ \ifvoid\b_typo_items_symbols \else
+ \box\b_typo_items_symbols
+ \itemsparameter\c!inbetween
+ \nointerlineskip
+ \fi
+ \box\b_typo_items_texts\
+ \egroup}
+
+\defineitems[\v!bottom][\c!width=\d_typo_items_text_width,\c!textalign=\itemsparameter\c!align]
+
+\setvalue{\??itemsalternatives\v!bottom}#1%
+ {\let\typo_items_make\typo_items_make_horizontal
+ \let\typo_items_item\typo_items_item_horizontal
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\vbox\bgroup
+ \forgetall
+ \box\b_typo_items_texts
+ \ifvoid\b_typo_items_symbols \else
+ \itemsparameter\c!inbetween
+ \nointerlineskip
+ \box\b_typo_items_symbols
+ \fi
+ \egroup}
+
+\defineitems[\v!inmargin][\c!width=1.5\emwidth,\c!align=\v!flushright,\c!distance=\leftmargindistance]
+
+\setvalue{\??itemsalternatives\v!inmargin}#1%
+ {\let\typo_items_make\typo_items_make_vertical
+ \let\typo_items_item\typo_items_item_vertical
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\hbox\bgroup
+ \ifvoid\b_typo_items_symbols \else
+ \llap{\box\b_typo_items_symbols\hskip\d_typo_items_distance}%
+ \fi
+ \box\b_typo_items_texts
+ \egroup}
+
+\defineitems[\v!left][\c!width=1.5\emwidth,\c!align=\v!flushleft]
+
+\setvalue{\??itemsalternatives\v!left}#1%
+ {\let\typo_items_make\typo_items_make_vertical
+ \let\typo_items_item\typo_items_item_vertical
+ \advance\d_typo_items_text_width-\dimexpr\d_typo_items_symbol_width+\d_typo_items_distance\relax
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\hbox\bgroup
+ \ifvoid\b_typo_items_symbols \else
+ \box\b_typo_items_symbols
+ \kern\d_typo_items_distance
+ \fi
+ \box\b_typo_items_texts
+ \egroup}
+
+\defineitems[\v!right][\c!width=1.5\emwidth,\c!align=\v!flushright]
+
+\setvalue{\??itemsalternatives\v!right}#1%
+ {\let\typo_items_make\typo_items_make_vertical
+ \let\typo_items_item\typo_items_item_vertical
+ \advance\d_typo_items_text_width-\dimexpr\d_typo_items_symbol_width+\d_typo_items_distance\relax
+ \typo_items_construct_items_boxes{#1}%
+ \noindent\hbox\bgroup
+ \box\b_typo_items_texts
+ \ifvoid\b_typo_items_symbols \else
+ \kern\d_typo_items_distance
+ \box\b_typo_items_symbols
+ \fi
+ \egroup}
+
+\protect \endinput
diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua
index 54b1fd2d3..e9b9f1f45 100644
--- a/tex/context/base/typo-krn.lua
+++ b/tex/context/base/typo-krn.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['typo-krn'] = {
local utf = unicode.utf8
-local next, type = next, type
+local next, type, tonumber = next, type, tonumber
local utfchar = utf.char
local nodes, node, fonts = nodes, node, fonts
@@ -31,6 +31,7 @@ local tasks = nodes.tasks
local new_gluespec = nodepool.gluespec
local new_kern = nodepool.kern
+local new_glue = nodepool.glue
local nodecodes = nodes.nodecodes
local kerncodes = nodes.kerncodes
@@ -55,6 +56,8 @@ local chardata = fonthashes.characters
local quaddata = fonthashes.quads
local markdata = fonthashes.marks
+local v_max = interfaces.variables.max
+
typesetters = typesetters or { }
local typesetters = typesetters
@@ -86,16 +89,45 @@ kerns.keeptogether = false -- just for fun (todo: control setting with key/value
-- can be optimized .. the prev thing .. but hardly worth the effort
+local function kern_injector(fillup,kern)
+ if fillup then
+ local g = new_glue(kern)
+ local s = g.spec
+ s.stretch = kern
+ s.stretch_order = 1
+ return g
+ else
+ return new_kern(kern)
+ end
+end
+
+local function spec_injector(fillup,width,stretch,shrink)
+ if fillup then
+ local s = new_gluespec(width,2*stretch,2*shrink)
+ s.stretch_order = 1
+ return s
+ else
+ return new_gluespec(width,stretch,shrink)
+ end
+end
+
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 fillup = false
while start do
-- faster to test for attr first
local attr = force or has_attribute(start,attribute)
if attr and attr > 0 then
unset_attribute(start,attribute)
local krn = mapping[attr]
+ if krn == v_max then
+ krn = .25
+ fillup = true
+ else
+ fillup = false
+ end
if krn and krn ~= 0 then
local id = start.id
if id == glyph_code then
@@ -155,12 +187,12 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that
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))
+ insert_node_before(head,start,kern_injector(fillup,krn))
done = true
end
else
krn = quaddata[lastfont]*krn -- here
- insert_node_before(head,start,new_kern(krn))
+ insert_node_before(head,start,kern_injector(fillup,krn))
done = true
end
elseif pid == disc_code then
@@ -218,7 +250,7 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that
else
krn = quaddata[lastfont]*krn -- here
end
- disc.replace = new_kern(krn)
+ disc.replace = kern_injector(fillup,krn)
end
end
end
@@ -229,7 +261,7 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that
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)
+ start.spec = spec_injector(fillup,width,stretch*width/w,shrink*width/w)
done = true
end
end
@@ -244,12 +276,12 @@ local function do_process(namespace,attribute,head,force) -- todo: glue so that
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
- insert_node_before(head,start,new_kern(quaddata[lastfont]*krn))
+ insert_node_before(head,start,kern_injector(fillup,quaddata[lastfont]*krn))
done = true
end
local n = start.next
if n and n.id ~= glue_code then
- insert_node_after(head,start,new_kern(quaddata[lastfont]*krn))
+ insert_node_after(head,start,kern_injector(fillup,quaddata[lastfont]*krn))
done = true
end
end
@@ -265,7 +297,10 @@ end
local enabled = false
function kerns.set(factor)
- if factor ~= 0 then
+ if factor ~= v_max then
+ factor = tonumber(factor) or 0
+ end
+ if factor == v_max or factor ~= 0 then
if not enabled then
tasks.enableaction("processors","typesetters.kerns.handler")
enabled = true
diff --git a/tex/context/base/typo-krn.mkiv b/tex/context/base/typo-krn.mkiv
index e1e404a7b..cb1dcdd18 100644
--- a/tex/context/base/typo-krn.mkiv
+++ b/tex/context/base/typo-krn.mkiv
@@ -40,7 +40,7 @@
\def\typo_kerning_set
{\usecharacterkerningstyleandcolor\c!style\c!color % goodie, maybe also strut
- \ctxcommand{setcharacterkerning(\characterkerningparameter\c!factor)}}
+ \ctxcommand{setcharacterkerning("\characterkerningparameter\c!factor")}}
\unexpanded\def\resetcharacterkerning % fast one
{\attribute\kernattribute\attributeunsetvalue}
@@ -62,8 +62,6 @@
%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
@@ -87,4 +85,57 @@
{\let\currentcharacterkerning\v!kerncharacters
\typo_kerning_set}
+%D \macros
+%D {stretched}
+%D
+%D Stretching characters in a word is a sort of typographical
+%D murder. Nevertheless we support this manipulation for use in
+%D for instance titles.
+%D
+%D \starttyping
+%D \hbox to 5cm{\stretched{to the limit}}
+%D \stretched{to the limit}
+%D \stretched[width=10cm]{to the limit}
+%D \stoptyping
+%D
+%D \typebuffer
+%D
+%D or
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D \showsetup{stretched}
+%D
+%D This command replaces the old \MKII\ variant.
+
+\definecharacterkerning
+ [\v!stretched]
+ [\c!factor=\v!max,
+ \c!width=\availablehsize]
+
+\unexpanded\def\setupstretched
+ {\setupcharacterkerning[\v!stretched]}
+
+\unexpanded\def\stretched
+ {\dosingleempty\typo_kerning_stretched}
+
+\unexpanded\def\typo_kerning_stretched[#1]#2%
+ {\begingroup
+ \let\currentcharacterkerning\v!stretched
+ \iffirstargument
+ \setupcurrentcharacterkerning[#1]%
+ \fi
+ \edef\p_width{\characterkerningparameter\c!width}%
+ \ifx\p_width\empty \else
+ \hbox to \p_width
+ \fi
+ \bgroup
+ \usecharacterkerningstyleandcolor\c!style\c!color
+ \typo_kerning_set
+ #2%
+ \egroup
+ \endgroup}
+
\protect \endinput
diff --git a/tex/context/base/typo-mar.lua b/tex/context/base/typo-mar.lua
index a21d9b70a..9252ef874 100644
--- a/tex/context/base/typo-mar.lua
+++ b/tex/context/base/typo-mar.lua
@@ -73,7 +73,7 @@ if not modules then modules = { } end modules ['typo-mar'] = {
-- so far
-local format = string.format
+local format, validstring = string.format, string.valid
local insert, remove = table.insert, table.remove
local setmetatable, next = setmetatable, next
@@ -81,6 +81,7 @@ 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_marginstack = false trackers.register("typesetters.margindata.stack", function(v) trace_marginstack = v end)
+local trace_margingroup = false trackers.register("typesetters.margindata.group", function(v) trace_margingroup = v end)
local report_margindata = logs.reporter("typesetters","margindata")
@@ -92,6 +93,7 @@ local enableaction = tasks.enableaction
local variables = interfaces.variables
local conditionals = tex.conditionals
+local systemmodes = tex.systemmodes
local v_top = variables.top
local v_depth = variables.depth
@@ -124,7 +126,7 @@ 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 concat_nodes = nodes.concat
local nodecodes = nodes.nodecodes
local listcodes = nodes.listcodes
@@ -138,6 +140,8 @@ local kern_code = nodecodes.kern
local penalty_code = nodecodes.penalty
local whatsit_code = nodecodes.whatsit
local line_code = listcodes.line
+local cell_code = listcodes.cell
+local alignment_code = listcodes.alignment
local leftskip_code = gluecodes.leftskip
local rightskip_code = gluecodes.rightskip
local userdefined_code = whatsitcodes.userdefined
@@ -229,23 +233,28 @@ local defaults = {
local enablelocal, enableglobal -- forward reference (delayed initialization)
-local function showstore(store,banner)
+local function showstore(store,banner,location)
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))
+ report_margindata("%s: stored in %s at %s: %s => %s",banner,location,i,validstring(si.name,"no name"),nodes.toutf(si.box.list))
end
else
- report_margindata("%s: nothing stored",banner)
+ report_margindata("%s: nothing stored in %s",banner,location)
end
end
function margins.save(t)
setmetatable(t,defaults)
- local inline = t.inline
+ local content = texbox[t.number]
local location = t.location
local category = t.category
- local scope = t.scope
+ local inline = t.inline
+ local scope = t.scope or v_global
+ if not content then
+ report_margindata("ignoring empty margin data: %s",location or "unknown")
+ return
+ end
local store
if inline then
store = inlinestore
@@ -263,15 +272,17 @@ function margins.save(t)
end
if enablelocal and scope == v_local then
enablelocal()
- end
- if enableglobal and scope == v_global then
+ if enableglobal then
+ enableglobal() -- is the fallback
+ end
+ elseif 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 ")
+ showstore(store,"before",location)
end
if name and name ~= "" then
if inlinestore then -- todo: inline store has to be done differently (not sparse)
@@ -292,12 +303,12 @@ function margins.save(t)
end
end
if trace_marginstack then
- showstore(store,"between")
+ showstore(store,"between",location)
end
end
if t.number then
-- better make a new table and make t entry in t
- t.box = copy_node_list(texbox[t.number])
+ t.box = copy_node_list(content)
t.n = nofsaved
-- used later (we will clean up this natural mess later)
-- nice is to make a special status table mechanism
@@ -327,7 +338,7 @@ function margins.save(t)
end
end
if trace_marginstack then
- showstore(store,"after ")
+ showstore(store,"after",location)
end
if trace_margindata then
report_margindata("saved: %s, location: %s, scope: %s, inline: %s",nofsaved,location,scope,tostring(inline))
@@ -409,7 +420,8 @@ local function realign(current,candidate)
if not anchor or anchor == "" then
anchor = v_text
end
- if inline or anchor ~= v_text then
+ if inline or anchor ~= v_text or candidate.psubtype == alignment_code then
+ -- the alignment_code check catches margintexts ste before a tabulate
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)
@@ -438,7 +450,7 @@ local function realign(current,candidate)
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.list = hpack_nodes(concat_nodes{anchornode,new_kern(-delta),current.list,new_kern(delta)})
current.width = 0
end
@@ -481,7 +493,7 @@ local function markovershoot(current)
v_anchors = v_anchors + 1
cache[v_anchors] = stacked
local anchor = new_latelua(format("typesetters.margins.ha(%s)",v_anchors)) -- todo: alleen als offset > line
- current.list = hpack_nodes(link_nodes(anchor,current.list))
+ current.list = hpack_nodes(concat_nodes{anchor,current.list})
end
local function getovershoot(location)
@@ -516,6 +528,7 @@ local function inject(parent,head,candidate)
local baseline = candidate.baseline
local strutheight = candidate.strutheight
local strutdepth = candidate.strutdepth
+ local psubtype = parent.subtype
local offset = stacked[location]
local firstonstack = offset == false or offset == nil
nofstatus = nofstatus + 1
@@ -538,8 +551,9 @@ local function inject(parent,head,candidate)
end
candidate.width = width
candidate.hsize = parent.width -- we can also pass textwidth
+ candidate.psubtype = psubtype
if trace_margindata then
- report_margindata("processing, index %s, height: %s, depth: %s",candidate.n,height,depth)
+ report_margindata("processing, index %s, height: %s, depth: %s, parent: %s",candidate.n,height,depth,listcodes[psubtype])
end
if firstonstack then
offset = 0
@@ -613,7 +627,7 @@ local function inject(parent,head,candidate)
elseif head.id == whatsit_code and head.subtype == localpar_code then
-- experimental
if head.dir == "TRT" then
- box.list = hpack_nodes(link_nodes(new_kern(candidate.hsize),box.list,new_kern(-candidate.hsize)))
+ box.list = hpack_nodes(concat_nodes{new_kern(candidate.hsize),box.list,new_kern(-candidate.hsize)})
end
insert_node_after(head,head,box)
else
@@ -708,11 +722,11 @@ local function flushed(scope,parent) -- current is hlist
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
+ 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")
-if a then
- set_attribute(parent.list,a_linenumber,a)
-end
+ if a then
+ set_attribute(parent.list,a_linenumber,a)
+ end
-- resetstacked()
end
return done, continue
@@ -754,29 +768,44 @@ local function handler(scope,head,group)
end
end
-function margins.localhandler(head,group)
- if conditionals.inhibitmargindata then
+function margins.localhandler(head,group) -- sometimes group is "" which is weird
+ local inhibit = conditionals.inhibitmargindata
+ if inhibit then
+ if trace_margingroup then
+ report_margindata("ignored: 3, group: %s, stored: %s, inhibit: %s",group,nofstored,tostring(inhibit))
+ end
return head, false
elseif nofstored > 0 then
return handler(v_local,head,group)
else
+ if trace_margingroup then
+ report_margindata("ignored: 4, group: %s, stored: %s, inhibit: %s",group,nofstored,tostring(inhibit))
+ end
return head, false
end
end
function margins.globalhandler(head,group) -- check group
--- print(group)
- if conditionals.inhibitmargindata or nofstored == 0 then
+ local inhibit = conditionals.inhibitmargindata
+ if inhibit or nofstored == 0 then
+ if trace_margingroup then
+ report_margindata("ignored: 1, group: %s, stored: %s, inhibit: %s",group,nofstored,tostring(inhibit))
+ end
return head, false
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:
+ -- 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)
+ elseif group == "alignment" then -- experiment (for alignments)
+ return handler("global",head,group)
else
+ if trace_margingroup then
+ report_margindata("ignored: 2, group: %s, stored: %s, inhibit: %s",group,nofstored,tostring(inhibit))
+ end
return head, false
end
end
@@ -823,12 +852,12 @@ end
-- go horizontal. So this needs more testing.
prependaction("finalizers", "lists", "typesetters.margins.localhandler")
--- prependaction("vboxbuilders", "normalizers", "typesetters.margins.localhandler")
+-- ("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")
+-- ("vboxbuilders", "typesetters.margins.localhandler")
disableaction("mvlbuilders", "typesetters.margins.globalhandler")
disableaction("shipouts", "typesetters.margins.finalhandler")
diff --git a/tex/context/base/typo-mar.mkiv b/tex/context/base/typo-mar.mkiv
index a393fc250..08d8b0cf0 100644
--- a/tex/context/base/typo-mar.mkiv
+++ b/tex/context/base/typo-mar.mkiv
@@ -110,7 +110,7 @@
% \c!align=,
% \c!method=,
\c!style=\v!bold,
- \c!color=, % maybe textcolor
+ \c!color=, % maybe \maintextcolor
% \c!name=,
% \c!category=,
\c!threshold=.25ex,
@@ -148,7 +148,7 @@
\appendtoks
\forgetall
\tf
- \deactivatecolor
+ \deactivatecolor % needed, but maybe we should switch to maintextcolor: \onlyinheritmaintextcolor
\to \everymargindatacontent
% trialtypesetting: no need for margin stuff while trialing as
@@ -243,7 +243,7 @@
\hsize\currentmargindatawidth
\raggedcommand
\ifx\currentmargindatastrut\empty \else
- \dosetupstrut[\currentmargindatastrut]%
+ \synchronizestrut\currentmargindatastrut
\fi
\begstrut
\strc_references_flush_destination_nodes
@@ -299,6 +299,7 @@
category = "\margindataparameter\c!category",
name = "\margindataparameter\c!name",
scope = "\margindataparameter\c!scope",
+ number = \number\nextbox,
}}%
\fi
\endgroup}
diff --git a/tex/context/base/typo-scr.mkiv b/tex/context/base/typo-scr.mkiv
index 4b4487522..6249c390a 100644
--- a/tex/context/base/typo-scr.mkiv
+++ b/tex/context/base/typo-scr.mkiv
@@ -19,7 +19,7 @@
%D \type {shiftup} and \type {shiftdown} that can work across paragraphs.
%D \macros
-%D {low, high, lohi, hilo}
+%D {low, high, definelow, definehigh, setuplow, setuphigh}
%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
@@ -36,69 +36,233 @@
%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.
+\installcorenamespace {low}
+\installcorenamespace {high}
-\def\highvfraction {0}
-\def\lowvfraction {0}
-\def\highlowvfraction{.1}
-\def\highlowhfraction{.1}
+\installcommandhandler \??low {low} \??low
+\installcommandhandler \??high {high} \??high
-\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}
+\setuplow [\c!style=\tx,\c!distance=\zeropoint,\c!down=.48\exheight] % historical
+\setuphigh[\c!style=\tx,\c!distance=\zeropoint,\c!up =.86\exheight] % values
-\def\typo_scripts_high_low#1#2#3#4#5#6% textscript mathscript fraction extra tag
+\appendtoks \setuevalue\currentlow {\typo_scripts_low {\currentlow }}\to \everydefinelow
+\appendtoks \setuevalue\currenthigh{\typo_scripts_high{\currenthigh}}\to \everydefinehigh
+
+\unexpanded\def\typo_scripts_low#1#2%
+ {\dontleavehmode
+ \begingroup
+ \edef\currentlow{#1}%
+ \kern\lowparameter\c!distance\relax
+ \setbox\scratchbox\hbox\bgroup
+ \lower\lowparameter\c!down\hbox\bgroup
+ \ifx\fontsize\empty
+ \ifmmode
+ \mr % no color yet
+ \else
+ \uselowstyleandcolor\c!style\c!color
+ \fi
+ \else
+ \uselowstyleandcolor\c!style\c!color
+ \fi
+ \dostarttagged\t!sub\currentlow
+ #2%
+ \dostoptagged
+ \egroup
+ \egroup
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\typo_scripts_high#1#2%
{\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
+ \edef\currenthigh{#1}%
+ \kern\highparameter\c!distance\relax
+ \setbox\scratchbox\hbox\bgroup
+ \raise\highparameter\c!up\hbox\bgroup
+ \ifx\fontsize\empty
+ \ifmmode
+ \mr % no color yet
+ \else
+ \usehighstyleandcolor\c!style\c!color
+ \fi
+ \else
+ \usehighstyleandcolor\c!style\c!color
+ \fi
+ \dostarttagged\t!sup\currenthigh
+ #2%
+ \dostoptagged
+ \egroup
+ \egroup
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
\box\scratchbox
\endgroup}
+\unexpanded\def\low {\typo_scripts_low \empty}
+\unexpanded\def\high{\typo_scripts_high\empty}
+
+%D \macros
+%D {lohi, hilo, definelohi, setuplohi}
+%D
%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 \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}
+\installcorenamespace {lowhigh}
+
+\installcommandhandler \??lowhigh {lowhigh} \??lowhigh
+
+\setuplowhigh
+ [\c!style=\tx,
+ \c!distance=.1\exheight, % these are
+ \c!up=.96\exheight, % historical
+ \c!down=.58\exheight] % values
-\def\typo_scripts_lohi[#1]#2#3%
+\appendtoks
+ \setuevalue\currentlowhigh{\typo_scripts_lowhigh{\currentlowhigh}\typo_scripts_lowhigh_indeed}%
+\to \everydefinelowhigh
+
+\unexpanded\def\typo_scripts_lowhigh#1% #2
{\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
+ \hbox\bgroup
+ \edef\currentlowhigh{#1}%
+ \dosingleempty} % #2
+
+\unexpanded\def\typo_scripts_lowhigh_indeed[#1]#2#3% todo: align .. [#1] is compatible hack
+ {\dostarttagged\t!subsup\currentlowhigh
+ \setbox\plusfour\hbox{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#2}}%
+ \setbox\plussix \hbox{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#3}}%
+ \doif{#1}{\v!left}
+ {\ifdim\wd\plusfour<\wd\plussix
+ \setbox\plusfour\hbox to \wd\plussix {\hss\box\plusfour}%
\else
- \wd6=\zeropoint\box6\box4
- \fi
- \dostoptagged}}
+ \setbox\plussix \hbox to \wd\plusfour{\hss\box\plussix }%
+ \fi}%
+ \ifdim\wd\plusfour<\wd\plussix
+ \wd\plusfour\zeropoint
+ \box\plusfour
+ \box\plussix
+ \else
+ \wd\plussix\zeropoint
+ \box\plussix
+ \box\plusfour
+ \fi
+ \dostoptagged
+ \egroup}
+
+\def\typo_scripts_lowhigh_low_high#1#2#3#4%
+ {\dontleavehmode
+ \begingroup
+ \kern\lowhighparameter\c!distance\relax
+ \setbox\scratchbox\hbox\bgroup
+ #1\lowhighparameter#2\hbox\bgroup
+ \ifx\fontsize\empty
+ \ifmmode
+ \mr % no color yet
+ \else
+ \uselowhighstyleandcolor\c!style\c!color
+ \fi
+ \else
+ \uselowhighstyleandcolor\c!style\c!color
+ \fi
+ \dostarttagged#3\empty
+ #4%
+ \dostoptagged
+ \egroup
+ \egroup
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox
+ \endgroup}
+
+\unexpanded\def\typo_scripts_highlow_indeed[#1]#2#3%
+ {\typo_scripts_lowhigh_indeed[#1]{#3}{#2}}
+
+\unexpanded\def\lohi{\typo_scripts_lowhigh\empty\typo_scripts_lowhigh_indeed}
+\unexpanded\def\hilo{\typo_scripts_lowhigh\empty\typo_scripts_highlow_indeed}
+
+%D \macros
+%D {lowmidhigh, definelowmidhigh, setuplowmidhigh}
+%D
+%D The previous command originally didn't have definers. These were introduced when
+%D the next showed up:
+%D
+%D \startbuffer
+%D \definelow [MyLow] [style=\txx]
+%D \definehigh [MyHigh] [style=\txx]
+%D \definelowhigh [MyLoHi] [style=\txx]
+%D \definelowmidhigh[MyLoMiHi][style=\txx]
+%D
+%D We have
+%D \ruledhbox{\low {L}} and \ruledhbox{\MyLow {L}} and
+%D \ruledhbox{\high {H}} and \ruledhbox{\MyHigh {H}} and
+%D \ruledhbox{\lohi {L}{H}} and \ruledhbox{\MyLoHi {L}{H}} and
+%D \ruledhbox{\lomihi{L}{M}{H}} and \ruledhbox{\MyLoMiHi{L}{M}{H}}.
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\installcorenamespace {lowmidhigh}
+
+\installcommandhandler \??lowmidhigh {lowmidhigh} \??lowmidhigh
+
+\setuplowmidhigh
+ [\c!style=\tx,
+ \c!up=.8\struthtdp,
+ \c!down=.8\struthtdp]
+
+\appendtoks
+ \setuevalue\currentlowmidhigh{\typo_scripts_lowmidhigh{\currentlowmidhigh}}%
+\to \everydefinelowmidhigh
+
+\unexpanded\def\typo_scripts_lowmidhigh#1#2#3#4%
+ {\dontleavehmode \hbox \bgroup
+ \edef\currentlowmidhigh{#1}%
+ \dostarttagged\t!subsup\currentlowmidhigh
+ \uselowmidhighstyleandcolor\c!style\c!color
+ \setstrut
+ \setbox\plustwo \hbox{\strut\dostarttagged\t!sub\empty#2\dostoptagged}%
+ \setbox\plusfour\hbox{\strut\dostarttagged\t!mid\empty#3\dostoptagged}% inefficient
+ \setbox\plussix \hbox{\strut\dostarttagged\t!sup\empty#4\dostoptagged}%
+ \scratchdimen \wd
+ \ifdim\wd\plustwo>\wd\plusfour
+ \ifdim\wd\plustwo>\wd\plussix
+ \plustwo
+ \else
+ \plussix
+ \fi
+ \else
+ \ifdim\wd\plusfour>\wd\plussix
+ \plusfour
+ \else
+ \plussix
+ \fi
+ \fi
+ \relax
+ \setbox\plustwo \hbox to \scratchdimen{\hss\lower\lowmidhighparameter\c!down\box\plustwo \hss}%
+ \setbox\plusfour\hbox to \scratchdimen{\hss \box\plusfour\hss}%
+ \setbox\plussix \hbox to \scratchdimen{\hss\raise\lowmidhighparameter\c!up \box\plussix \hss}%
+ \wd\plustwo \zeropoint
+ \wd\plusfour\zeropoint
+ \box\plusfour
+ \box\plustwo
+ \box\plussix
+ \dostoptagged
+ \egroup}
-\def\typo_scripts_hilo[#1]#2#3%
- {\typo_scripts_lohi[#1]{#3}{#2}}
+\unexpanded\def\lomihi {\typo_scripts_lowmidhigh\empty}
+\unexpanded\def\himilo#1#2#3{\typo_scripts_lowmidhigh\empty{#3}{#2}{#1}}
\protect \endinput
diff --git a/tex/context/base/typo-spa.mkiv b/tex/context/base/typo-spa.mkiv
index 0cfe44610..df2dab47c 100644
--- a/tex/context/base/typo-spa.mkiv
+++ b/tex/context/base/typo-spa.mkiv
@@ -25,7 +25,12 @@
\installcorenamespace{characterspacing}
-\definesystemvariable{cs} % maybe a dummy namespace
+\installsetuponlycommandhandler \??characterspacing {_p_characterspacing} % private
+
+\setup_p_characterspacing
+ [\c!left=0,
+ \c!right=0,
+ \c!alternative=0]
\unexpanded\def\definecharacterspacing[#1]%
{\ctxcommand{definecharacterspacing("#1")}}
@@ -35,11 +40,11 @@
\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
+ \setupcurrent_p_characterspacing[#3]%
+ \ctxcommand{setupcharacterspacing("#1",\number#2, { % todo: just pass #3 to the lua end
+ left = \direct_p_characterspacingparameter\c!left,
+ right = \direct_p_characterspacingparameter\c!right,
+ alternative = \direct_p_characterspacingparameter\c!alternative
})}%
\endgroup}
diff --git a/tex/context/base/typo-txt.mkvi b/tex/context/base/typo-txt.mkvi
index f2859b58f..f1c80c1bd 100644
--- a/tex/context/base/typo-txt.mkvi
+++ b/tex/context/base/typo-txt.mkvi
@@ -2,7 +2,7 @@
%D [ file=typo-txt,
%D version=2011.10.27,
%D title=\CONTEXT\ Typesetting Macros,
-%D subtitle=Texts,
+%D subtitle=Text Hacks,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
@@ -13,12 +13,63 @@
%D This module replaces the by now rather old supp-fun module.
+\writestatus{loading}{ConTeXt Typesetting Macros / Text Hacks}
+
\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}
+\registerctxluafile{typo-txt}{1.001}
+
+%D \macros
+%D {normalizefontheight,normalizefontwidth,normalizedfontsize}
+%D
+%D Next we introduce some font manipulation macros. When we
+%D want to typeset some text spread in a well defined area, it
+%D can be considered bad practice to manipulate character and
+%D word spacing. In such situations the next few macros can be
+%D of help:
+%D
+%D \starttyping
+%D \normalizefontheight \name {sample text} {height} {font}
+%D \normalizefontwidth \name {sample text} {width} {font}
+%D \stoptyping
+%D
+%D Consider for instance:
+%D
+%D \startbuffer[a]
+%D \NormalizeFontHeight \TempFont {X} {2\baselineskip} {Serif}
+%D \stopbuffer
+%D
+%D \startbuffer[b]
+%D \ruledhbox{\TempFont To Be Or Not To Be}
+%D \stopbuffer
+%D
+%D \typebuffer[a,b] \getbuffer[a]
+%D
+%D This shows up as:
+%D
+%D \startlinecorrection
+%D \ruledhbox{\getbuffer[b]}
+%D \stoplinecorrection
+%D
+%D The horizontal counterpart is:
+%D
+%D \startbuffer[a]
+%D \NormalizeFontWidth \TempFont {This Line Fits} {\hsize} {Serif}
+%D \stopbuffer
+%D
+%D \startbuffer[b]
+%D \ruledhbox{\TempFont This Line Fits}
+%D \stopbuffer
+%D
+%D \typebuffer[a,b] \getbuffer[a]
+%D
+%D This gives:
+%D
+%D \startlinecorrection
+%D \ruledhbox{\getbuffer[b]}
+%D \stoplinecorrection
+%D
+%D The calculated font scale is avaliable in \type {\normalizedfontsize}.
\newbox\b_typo_normalizers
@@ -26,14 +77,14 @@
{\dimexpr\ifdim#1\b_typo_normalizers=\zeropoint
\bodyfontsize
\else
- \cldcontext{\number\dimexpr10pt\relax*\number\dimexpr#size\relax/\number#axis\b_typo_normalizers}\scaledpoint
+ \luaexpr{\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]}}
+ \normalexpanded{\endgroup\edef\noexpand\normalizedfontsize{\the\typo_normalizers_size{#axis}{#size}}}%
+ \definefont[\strippedcsname#cs][#font at \normalizedfontsize]}
\unexpanded\def\typo_normalizers_text_at_size#axis#font#size#text%
{\dontleavehmode
@@ -42,30 +93,105 @@
\definedfont[#font at \the\typo_normalizers_size{#axis}{#size}]#text%
\endgroup}
-\let\TheNormalizedFontSize\!!zeropoint
+\def\normalizedfontsize{\bodyfontsize}
+
+\unexpanded\def\normalizetextwidth {\typo_normalizers_text_at_size\wd}
+\unexpanded\def\normalizetextheight{\typo_normalizers_text_at_size\ht}
+\unexpanded\def\normalizetextdepth {\typo_normalizers_text_at_size\dp}
+\unexpanded\def\normalizetextline {\typo_normalizers_text_at_size\htdp}
+
+\unexpanded\def\normalizefontwidth {\typo_normalizers_font_at_size\wd}
+\unexpanded\def\normalizefontheight{\typo_normalizers_font_at_size\ht}
+\unexpanded\def\normalizefontdepth {\typo_normalizers_font_at_size\dp}
+\unexpanded\def\normalizefontline {\typo_normalizers_font_at_size\htdp}
-%D Traditionally we use UpperCasedNames for this kind of
-%D functionality.
+\unexpanded\def\widthspanningtext #text#size#specification{\hbox{\normalizefontwidth \temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\heightspanningtext#text#size#specification{\hbox{\normalizefontheight\temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\depthspanningtext #text#size#specification{\hbox{\normalizefontdepth \temp{#text}{#size}{#specification}\temp#text}}
+\unexpanded\def\linespanningtext #text#size#specification{\hbox{\normalizefontline \temp{#text}{#size}{#specification}\temp#text}}
-\unexpanded\def\NormalizeFontHeight{\typo_normalizers_font_at_size\ht}
-\unexpanded\def\NormalizeFontWidth {\typo_normalizers_font_at_size\wd}
+%D Traditionally we use UpperCasedNames for this kind of functionality.
-\unexpanded\def\NormalizeTextHeight{\typo_normalizers_text_at_size\ht}
-\unexpanded\def\NormalizeTextWidth {\typo_normalizers_text_at_size\wd}
+\let\NormalizeFontHeight \normalizefontheight
+\let\NormalizeFontWidth \normalizefontwidth
+\let\NormalizeTextHeight \normalizetextheight
+\let\NormalizeTextWidth \normalizetextwidth
-\unexpanded\def\WidthSpanningText#text#width#font% compatibility macro
- {\hbox{\NormalizeFontWidth\temp{#text}{#width}{#font}\temp\the\everydefinedfont#1}}
+\let\WidthSpanningText \widthspanningtext
+\def\TheNormalizedFontSize{\normalizedfontsize}
+
+%D \macros
+%D {vulgarfraction}
+%D
+%D This code is moved from \type {cor-mis.mkiv}. We show three versions. First
+%D the simple one using \type {\low} and \type {high}:
+%D
%D \startbuffer
-%D \NormalizeFontWidth \MyFontName {sample text} {10cm} {Serif*default}
+%D \def\vfrac#1#2%
+%D {\hbox{\high{\tx#1\kern-.25em}/\low{\kern-.25em\tx#2}}}
+%D
+%D test \vfrac{1}{2} test \vfrac{123}{456} test
+%D \stopbuffer
+%D
+%D \typebuffer {\showmakeup\getbuffer}
+%D
+%D A better way to handle the kerning is the following, here we kind of assume
+%D that tye slash is symmetrical and has nearly zero width.
%D
-%D \ruledhbox{\MyFontName sample text}
-%D \blank
-%D \blackrule[width=10cm]
-%D \blank
-%D \ruledhbox{\NormalizeTextWidth {Serif*default} {10cm} {sample text}}
+%D \startbuffer
+%D \def\vfract#1#2%
+%D {\hbox{\high{\tx#1}\hbox to \zeropoint{\hss/\hss}\low{\tx#2}}}
%D \stopbuffer
%D
-%D \typebuffer \getbuffer
+%D \typebuffer {\showmakeup\getbuffer}
+%D
+%D The third and best alternative is the following:
+%D
+%D {\showmakeup\getbuffer}\crlf\getbuffer
+%D
+%D This time we measure the height of the \type {/} and shift over the maximum
+%D height and depths of this character and the fractional digits (we use 57 as
+%D sample). Here we combine all methods in one macros.
+
+\setnewconstant\vulgarfractionmethod\plusthree
+
+\definehspace[\v!vulgarfraction][.25em] % [.15em]
+\definesymbol[\v!vulgarfraction][/] % [\raise.2ex\hbox{/}]
+
+\unexpanded\def\vulgarfraction#1#2%
+ {\dontleavehmode
+ \hbox
+ {\def\vulgarfraction{vulgarfraction}%
+ \ifcase\vulgarfractionmethod
+ #1\symbol[\v!vulgarfraction]#2%
+ \or
+ \high{\tx#1\kern-\hspaceamount\empty\v!vulgarfraction}%
+ \symbol[\vulgarfraction]%
+ \low {\kern-\hspaceamount\empty\v!vulgarfraction\tx#2}%
+ \or
+ \high{\tx#1}%
+ \hbox to \zeropoint{\hss\symbol[\v!vulgarfraction]\hss}%
+ \low{\tx#2}%
+ \or
+ \setbox0\hbox{\symbol[\vulgarfraction]}%
+ \setbox2\hbox{\txx57}%
+ \raise\ht0\hbox{\lower\ht2\hbox{\txx#1}}%
+ \hbox to \zeropoint{\hss\symbol[\v!vulgarfraction]\hss}%
+ \lower\dp0\hbox{\raise\dp2\hbox{\txx#2}}%
+ \fi}}
+
+\ifdefined\vfrac \else \let\vfrac\vulgarfraction \fi
+
+%D \starttabulate[|l|l|]
+%D \HL
+%D \NC \bf method \NC \bf visualization \NC\NR
+%D \HL
+%D \NC 0 \NC \vulgarfractionmethod0 \vulgarfraction{1}{2} \NC\NR
+%D \NC 1 \NC \vulgarfractionmethod1 \vulgarfraction{1}{2} \NC\NR
+%D \NC 2 \NC \vulgarfractionmethod2 \vulgarfraction{1}{2} \NC\NR
+%D \NC 3 \NC \vulgarfractionmethod3 \vulgarfraction{1}{2} \NC\NR
+%D \HL
+%D \stoptabulate
\protect \endinput
diff --git a/tex/context/base/unic-ini.mkiv b/tex/context/base/unic-ini.mkiv
index 55764dbdc..ece0da283 100644
--- a/tex/context/base/unic-ini.mkiv
+++ b/tex/context/base/unic-ini.mkiv
@@ -30,7 +30,7 @@
\def\unicodechar#1{\ctxcommand{unicodechar("#1")}}
\unexpanded\def\unknownchar
- {\dontleavehmode\hbox{\vrule\!!width.5em\!!height1ex\!!depth\zeropoint}}
+ {\dontleavehmode\hbox{\vrule\s!width.5\emwidth\s!height\exheight\s!depth\zeropoint}}
\ifdefined\zwnbsp\else \let\zwnbsp\relax \fi % zerowidthnonbreakablespace
diff --git a/tex/context/base/util-deb.lua b/tex/context/base/util-deb.lua
index d82c1a114..33d43b25f 100644
--- a/tex/context/base/util-deb.lua
+++ b/tex/context/base/util-deb.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['util.deb'] = {
+if not modules then modules = { } end modules ['util-deb'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -122,6 +122,7 @@ function inspect(i) -- global function
else
print(tostring(i))
end
+ return i -- so that we can inline the inspect
end
-- from the lua book:
diff --git a/tex/context/base/util-dim.lua b/tex/context/base/util-dim.lua
index 47e43c386..4bae2d099 100644
--- a/tex/context/base/util-dim.lua
+++ b/tex/context/base/util-dim.lua
@@ -16,7 +16,7 @@ table.</p>
--ldx]]--
local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable
-local P, S, R, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.match
+local P, S, R, Cc, C, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.Cc, lpeg.C, lpeg.match
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -141,6 +141,12 @@ local dimenpair = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is
lpeg.patterns.dimenpair = dimenpair
+local splitter = amount/tonumber * C(unit^1)
+
+function number.splitdimen(str)
+ return lpegmatch(splitter,str)
+end
+
--[[ldx--
<p>We use a metatable to intercept errors. When no key is found in
the table with factors, the metatable will be consulted for an
@@ -430,12 +436,12 @@ probably use a hash instead of a one-element table.</p>
<p>Goodie:s</p>
--ldx]]--
-function number.percent(n) -- will be cleaned up once luatex 0.30 is out
- local hsize = tex.hsize
- if type(hsize) == "string" then
- hsize = stringtodimen(hsize)
+function number.percent(n,d) -- will be cleaned up once luatex 0.30 is out
+ d = d or tex.hsize
+ if type(d) == "string" then
+ d = stringtodimen(d)
end
- return (n/100) * hsize
+ return (n/100) * d
end
number["%"] = number.percent
diff --git a/tex/context/base/util-jsn.lua b/tex/context/base/util-jsn.lua
new file mode 100644
index 000000000..7493f108d
--- /dev/null
+++ b/tex/context/base/util-jsn.lua
@@ -0,0 +1,145 @@
+if not modules then modules = { } end modules ['util-jsn'] = {
+ version = 1.001,
+ comment = "companion to m-json.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Of course we could make a nice complete parser with proper error messages but
+-- as json is generated programmatically errors are systematic and we can assume
+-- a correct stream. If not, we have some fatal error anyway. So, we can just rely
+-- on strings being strings (apart from the unicode escape which is not in 5.1) and
+-- as we first catch known types we just assume that anything else is a number.
+
+local P, V, R, S, C, Cc, Cs, Ct, Cf, Cg = lpeg.P, lpeg.V, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cg
+local lpegmatch = lpeg.match
+local format = string.format
+local utfchar = utf.char
+local concat = table.concat
+
+local tonumber, tostring, rawset, type = tonumber, tostring, rawset, type
+
+local json = utilities.json or { }
+utilities.json = json
+
+-- moduledata = moduledata or { }
+-- moduledata.json = json
+
+-- \\ \/ \b \f \n \r \t \uHHHH
+
+local lbrace = P("{")
+local rbrace = P("}")
+local lparent = P("[")
+local rparent = P("]")
+local comma = P(",")
+local colon = P(":")
+local dquote = P('"')
+
+local whitespace = lpeg.patterns.whitespace
+local optionalws = whitespace^0
+
+local escape = C(P("\\u") / "0x" * S("09","AF","af")) / function(s) return utfchar(tonumber(s)) end
+local jstring = dquote * Cs((escape + (1-dquote))^0) * dquote
+local jtrue = P("true") * Cc(true)
+local jfalse = P("false") * Cc(false)
+local jnull = P("null") * Cc(nil)
+local jnumber = (1-whitespace-rparent-rbrace-comma)^1 / tonumber
+
+local key = jstring
+
+local jsonconverter = { "value",
+ object = lbrace * Cf(Ct("") * V("pair") * (comma * V("pair"))^0,rawset) * rbrace,
+ pair = Cg(optionalws * key * optionalws * colon * V("value")),
+ array = Ct(lparent * V("value") * (comma * V("value"))^0 * rparent),
+ value = optionalws * (jstring + V("object") + V("array") + jtrue + jfalse + jnull + jnumber + #rparent) * optionalws,
+}
+
+-- local jsonconverter = { "value",
+-- object = lbrace * Cf(Ct("") * V("pair") * (comma * V("pair"))^0,rawset) * rbrace,
+-- pair = Cg(optionalws * V("string") * optionalws * colon * V("value")),
+-- array = Ct(lparent * V("value") * (comma * V("value"))^0 * rparent),
+-- string = jstring,
+-- value = optionalws * (V("string") + V("object") + V("array") + jtrue + jfalse + jnull + jnumber) * optionalws,
+-- }
+
+-- lpeg.print(jsonconverter) -- size 181
+
+function json.tolua(str)
+ return lpegmatch(jsonconverter,str)
+end
+
+local function tojson(value,t) -- we could optimize #t
+ local kind = type(value)
+ if kind == "table" then
+ local done = false
+ local size = #value
+ if size == 0 then
+ for k, v in next, value do
+ if done then
+ t[#t+1] = ","
+ else
+ t[#t+1] = "{"
+ done = true
+ end
+ t[#t+1] = format("%q:",k)
+ tojson(v,t)
+ end
+ if done then
+ t[#t+1] = "}"
+ else
+ t[#t+1] = "{}"
+ end
+ elseif size == 1 then
+ -- we can optimize for non tables
+ t[#t+1] = "["
+ tojson(value[1],t)
+ t[#t+1] = "]"
+ else
+ for i=1,size do
+ if done then
+ t[#t+1] = ","
+ else
+ t[#t+1] = "["
+ done = true
+ end
+ tojson(value[i],t)
+ end
+ t[#t+1] = "]"
+ end
+ elseif kind == "string" then
+ t[#t+1] = format("%q",value)
+ elseif kind == "number" then
+ t[#t+1] = value
+ elseif kind == "boolean" then
+ t[#t+1] = tostring(value)
+ end
+ return t
+end
+
+function json.tostring(value)
+ -- todo optimize for non table
+ local kind = type(value)
+ if kind == "table" then
+ return concat(tojson(value,{}),"")
+ elseif kind == "string" or kind == "number" then
+ return value
+ else
+ return tostring(value)
+ end
+end
+
+-- local tmp = [[ { "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]]
+
+-- tmp = json.tolua(tmp)
+-- inspect(tmp)
+-- tmp = json.tostring(tmp)
+-- inspect(tmp)
+-- tmp = json.tolua(tmp)
+-- inspect(tmp)
+-- tmp = json.tostring(tmp)
+-- inspect(tmp)
+
+-- inspect(json.tostring(true))
+
+return json
diff --git a/tex/context/base/util-lua.lua b/tex/context/base/util-lua.lua
index b49e93beb..2baeaa854 100644
--- a/tex/context/base/util-lua.lua
+++ b/tex/context/base/util-lua.lua
@@ -2,36 +2,208 @@ if not modules then modules = { } end modules ['util-lua'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment = "the strip code is written by Peter Cawley",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-utilities = utilities or {}
-utilities.lua = utilities.lua or { }
-utilities.report = logs and logs.reporter("system") or print
+local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
+local loadstring, loadfile, type = loadstring, loadfile, type
-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)
+utilities = utilities or {}
+utilities.lua = utilities.lua or { }
+local luautilities = utilities.lua
+
+utilities.report = logs and logs.reporter("system") or print -- can be overloaded later
+
+local tracestripping = false
+local forcestupidcompile = true -- use internal bytecode compiler
+luautilities.stripcode = true -- support stripping when asked for
+luautilities.alwaysstripcode = false -- saves 1 meg on 7 meg compressed format file (2012.08.12)
+luautilities.nofstrippedchunks = 0
+luautilities.nofstrippedbytes = 0
+
+-- The next function was posted by Peter Cawley on the lua list and strips line
+-- number information etc. from the bytecode data blob. We only apply this trick
+-- when we store data tables. Stripping makes the compressed format file about
+-- 1MB smaller (and uncompressed we save at least 6MB).
+--
+-- You can consider this feature an experiment, so it might disappear. There is
+-- no noticeable gain in runtime although the memory footprint should be somewhat
+-- smaller (and the file system has a bit less to deal with).
+--
+-- Begin of borrowed code ... works for Lua 5.1 which LuaTeX currently uses ...
+
+local function strip_code_pc(dump,name)
+ local before = #dump
+ local version, format, endian, int, size, ins, num = byte(dump,5,11)
+ local subint
+ if endian == 1 then
+ subint = function(dump, i, l)
+ local val = 0
+ for n = l, 1, -1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
+ end
+ else
+ subint = function(dump, i, l)
+ local val = 0
+ for n = 1, l, 1 do
+ val = val * 256 + byte(dump,i + n - 1)
+ end
+ return val, i + l
+ end
+ end
+ local strip_function
+ strip_function = function(dump)
+ local count, offset = subint(dump, 1, size)
+ local stripped, dirty = rep("\0", size), offset + count
+ offset = offset + count + int * 2 + 4
+ offset = offset + int + subint(dump, offset, int) * ins
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ local t
+ t, offset = subint(dump, offset, 1)
+ if t == 1 then
+ offset = offset + 1
+ elseif t == 4 then
+ offset = offset + size + subint(dump, offset, size)
+ elseif t == 3 then
+ offset = offset + num
+ end
+ end
+ count, offset = subint(dump, offset, int)
+ stripped = stripped .. sub(dump,dirty, offset - 1)
+ for n = 1, count do
+ local proto, off = strip_function(sub(dump,offset, -1))
+ stripped, offset = stripped .. proto, offset + off - 1
+ end
+ offset = offset + subint(dump, offset, int) * int + int
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size + int * 2
+ end
+ count, offset = subint(dump, offset, int)
+ for n = 1, count do
+ offset = offset + subint(dump, offset, size) + size
+ end
+ stripped = stripped .. rep("\0", int * 3)
+ return stripped, offset
+ end
+ dump = sub(dump,1,12) .. strip_function(sub(dump,13,-1))
+ local after = #dump
+ local delta = before-after
+ if tracestripping then
+ utilities.report("stripped bytecode: %s, before %s, after %s, delta %s",name or "unknown",before,after,delta)
+ end
+ luautilities.nofstrippedchunks = luautilities.nofstrippedchunks + 1
+ luautilities.nofstrippedbytes = luautilities.nofstrippedbytes + delta
+ return dump, delta
+end
+
+-- ... end of borrowed code.
+
+local function strippedbytecode(code,forcestrip,name)
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ return strip_code_pc(code,name)
+ else
+ return code, 0
+ end
+end
+
+luautilities.stripbytecode = strip_code_pc
+luautilities.strippedbytecode = strippedbytecode
+
+local function fatalerror(name)
+ utilities.report(format("fatal error in %q",name or "unknown"))
+end
+
+-- quite subtle ... doing this wrong incidentally can give more bytes
+
+
+function luautilities.loadedluacode(fullname,forcestrip,name)
+ -- quite subtle ... doing this wrong incidentally can give more bytes
+ name = name or fullname
+ local code = loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip) == "function" then
+ forcestrip = forcestrip(fullname)
+ end
+ if forcestrip then
+ local code, n = strip_code_pc(dump(code,name))
+ return loadstring(code), n
+ elseif luautilities.alwaysstripcode then
+ return loadstring(strip_code_pc(dump(code),name))
+ else
+ return code, 0
+ end
+ elseif luautilities.alwaysstripcode then
+ return loadstring(strip_code_pc(dump(code),name))
+ else
+ return code, 0
+ end
+end
+
+function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
+ local n = 0
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ code = loadstring(code)
+ if not code then
+ fatalerror(name)
end
+ code, n = strip_code_pc(dump(code),name)
end
+ return loadstring(code), n
end
-function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile,strip)
+ local code = io.loaddata(luafile)
+ local n = 0
+ if code and code ~= "" then
+ code = loadstring(code)
+ if not code then
+ fatalerror()
+ end
+ code = dump(code)
+ if strip then
+ code, n = strippedbytecode(code,true,luafile) -- last one is reported
+ end
+ if code and code ~= "" then
+ io.savedata(lucfile,code)
+ end
+ end
+ return n
+end
+
+local luac_normal = "texluac -o %q %q"
+local luac_strip = "texluac -s -o %q %q"
+
+function luautilities.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)
+ local done = false
if strip ~= false then
- command = "-s " .. command
+ strip = true
+ end
+ if forcestupidcompile then
+ fallback = true
+ elseif strip then
+ done = os.spawn(format(luac_strip, lucfile,luafile)) == 0
+ else
+ done = os.spawn(format(luac_normal,lucfile,luafile)) == 0
end
- 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
+ local n = stupidcompile(luafile,lucfile,strip)
+ if n > 0 then
+ utilities.report("lua: %s dumped into %s (%i bytes stripped)",luafile,lucfile,n)
+ else
+ utilities.report("lua: %s dumped into %s (unstripped)",luafile,lucfile)
+ end
+ cleanup = false -- better see how bad it is
end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
@@ -39,16 +211,15 @@ function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaul
end
return done
end
-
--~ local getmetatable, type = getmetatable, type
--~ local types = { }
---~ function utilities.lua.registerdatatype(d,name)
+--~ function luautilities.registerdatatype(d,name)
--~ types[getmetatable(d)] = name
--~ end
---~ function utilities.lua.datatype(d)
+--~ function luautilities.datatype(d)
--~ local t = type(d)
--~ if t == "userdata" then
--~ local m = getmetatable(d)
@@ -58,6 +229,6 @@ end
--~ end
--~ end
---~ utilities.lua.registerdatatype(lpeg.P("!"),"lpeg")
+--~ luautilities.registerdatatype(lpeg.P("!"),"lpeg")
---~ print(utilities.lua.datatype(lpeg.P("oeps")))
+--~ print(luautilities.datatype(lpeg.P("oeps")))
diff --git a/tex/context/base/util-mrg.lua b/tex/context/base/util-mrg.lua
index acf04fead..8d6c5dd31 100644
--- a/tex/context/base/util-mrg.lua
+++ b/tex/context/base/util-mrg.lua
@@ -13,11 +13,10 @@ local concat = table.concat
local type, next = type, next
utilities = utilities or {}
-utilities.merger = utilities.merger or { } -- maybe mergers
+local merger = utilities.merger or { }
+utilities.merger = merger
utilities.report = logs and logs.reporter("system") or print
-local merger = utilities.merger
-
merger.strip_comment = true
local m_begin_merge = "begin library merge"
@@ -63,9 +62,11 @@ end
local function self_save(name, data)
if data ~= "" then
if merger.strip_comment then
- -- saves some 20K
local n = #data
+ -- saves some 20K .. scite comments
data = gsub(data,"%-%-~[^\n\r]*[\r\n]","")
+ -- saves some 20K .. ldx comments
+ data = gsub(data,"%-%-%[%[ldx%-%-.-%-%-ldx%]%]%-%-","")
utilities.report("merge: %s bytes of comment stripped, %s bytes of code left",n-#data,#data)
end
io.savedata(name,data)
diff --git a/tex/context/base/util-prs.lua b/tex/context/base/util-prs.lua
index ab1bfb8eb..e7191d0e9 100644
--- a/tex/context/base/util-prs.lua
+++ b/tex/context/base/util-prs.lua
@@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-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 lpeg, table, string = lpeg, table, string
+
+local P, R, V, S, C, Ct, Cs, Carg, Cc = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cc
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
@@ -19,29 +21,39 @@ parsers.patterns = parsers.patterns or { }
local setmetatableindex = table.setmetatableindex
local sortedhash = table.sortedhash
+-- we share some patterns
+
+local space = P(' ')
+local equal = P("=")
+local comma = P(",")
+local lbrace = P("{")
+local rbrace = P("}")
+local period = S(".")
+local punctuation = S(".,:;")
+local spacer = patterns.spacer
+local whitespace = patterns.whitespace
+local newline = patterns.newline
+local anything = patterns.anything
+local endofstring = patterns.endofstring
+
-- we could use a Cf Cg construct
local escape, left, right = P("\\"), P('{'), P('}')
-lpeg.patterns.balanced = P {
+patterns.balanced = P {
[1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0,
[2] = left * V(1) * right
}
-local space = P(' ')
-local equal = P("=")
-local comma = P(",")
-local lbrace = P("{")
-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
+local content = (1-endofstring)^0
-lpeg.patterns.nested = nested -- no capture
-lpeg.patterns.argument = argument -- argument after e.g. =
-lpeg.patterns.content = content -- rest after e.g =
+patterns.nested = nested -- no capture
+patterns.argument = argument -- argument after e.g. =
+patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -60,10 +72,6 @@ local function set(key,value)
hash[key] = value
end
-local function set(key,value)
- hash[key] = value
-end
-
local pattern_a_s = (pattern_a/set)^1
local pattern_b_s = (pattern_b/set)^1
local pattern_c_s = (pattern_c/set)^1
@@ -114,7 +122,7 @@ end
local separator = comma * space^0
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-local pattern = Ct(value*(separator*value)^0)
+local pattern = spaces * Ct(value*(separator*value)^0)
-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
@@ -237,3 +245,34 @@ end
function parsers.listitem(str)
return gmatch(str,"[^, ]+")
end
+
+--
+local digit = R("09")
+
+local pattern = Cs { "start",
+ start = V("one") + V("two") + V("three"),
+ rest = (Cc(",") * V("thousand"))^0 * (P(".") + endofstring) * anything^0,
+ thousand = digit * digit * digit,
+ one = digit * V("rest"),
+ two = digit * digit * V("rest"),
+ three = V("thousand") * V("rest"),
+}
+
+patterns.splitthousands = pattern -- maybe better in the parsers namespace ?
+
+function parsers.splitthousands(str)
+ return lpegmatch(pattern,str) or str
+end
+
+-- print(parsers.splitthousands("11111111111.11"))
+
+local optionalwhitespace = whitespace^0
+
+patterns.words = Ct((Cs((1-punctuation-whitespace)^1) + anything)^1)
+patterns.sentences = Ct((optionalwhitespace * Cs((1-period)^0 * period))^1)
+patterns.paragraphs = Ct((optionalwhitespace * Cs((whitespace^1*endofstring/"" + 1 - (spacer^0*newline*newline))^1))^1)
+
+-- local str = " Word1 word2. \n Word3 word4. \n\n Word5 word6.\n "
+-- inspect(lpegmatch(patterns.paragraphs,str))
+-- inspect(lpegmatch(patterns.sentences,str))
+-- inspect(lpegmatch(patterns.words,str))
diff --git a/tex/context/base/util-sql-imp-client.lua b/tex/context/base/util-sql-imp-client.lua
new file mode 100644
index 000000000..8e174fc99
--- /dev/null
+++ b/tex/context/base/util-sql-imp-client.lua
@@ -0,0 +1,253 @@
+if not modules then modules = { } end modules ['util-sql-client'] = {
+ version = 1.001,
+ comment = "companion to util-sql.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: make a converter
+
+local rawset, setmetatable = rawset, setmetatable
+local P, S, V, C, Cs, Ct, Cc, Cg, Cf, patterns, lpegmatch = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.patterns, lpeg.match
+
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql","client")
+
+local sql = require("util-sql")
+local helpers = sql.helpers
+local methods = sql.methods
+local validspecification = helpers.validspecification
+local preparetemplate = helpers.preparetemplate
+local splitdata = helpers.splitdata
+local replacetemplate = utilities.templates.replace
+local serialize = sql.serialize
+local deserialize = sql.deserialize
+
+-- Experiments with an p/action demonstrated that there is not much gain. We could do a runtime
+-- capture but creating all the small tables is not faster and it doesn't work well anyway.
+
+local separator = P("\t")
+local newline = patterns.newline
+local empty = Cc("")
+
+local entry = C((1-separator-newline)^0) -- C 10% faster than Cs
+
+local unescaped = P("\\n") / "\n"
+ + P("\\t") / "\t"
+ + P("\\0") / "\000"
+ + P("\\\\") / "\\"
+
+local entry = Cs((unescaped + (1-separator-newline))^0) -- C 10% faster than Cs but Cs needed due to nesting
+
+local getfirst = Ct( entry * (separator * (entry+empty))^0) + newline
+local skipfirst = (1-newline)^1 * newline
+local getfirstline = C((1-newline)^0)
+
+local cache = { }
+
+local function splitdata(data) -- todo: hash on first line ... maybe move to client module
+ if data == "" then
+ if trace_sql then
+ report_state("no data")
+ end
+ return { }, { }
+ end
+ local first = lpegmatch(getfirstline,data)
+ if not first then
+ if trace_sql then
+ report_state("no data")
+ end
+ return { }, { }
+ end
+ local p = cache[first]
+ if p then
+ -- report_state("reusing: %s",first)
+ local entries = lpegmatch(p.parser,data)
+ return entries or { }, p.keys
+ elseif p == false then
+ return { }, { }
+ elseif p == nil then
+ local keys = lpegmatch(getfirst,first) or { }
+ if #keys == 0 then
+ if trace_sql then
+ report_state("no banner")
+ end
+ cache[first] = false
+ return { }, { }
+ end
+ -- quite generic, could be a helper
+ local n = #keys
+ if n == 0 then
+ report_state("no fields")
+ cache[first] = false
+ return { }, { }
+ end
+ if n == 1 then
+ local key = keys[1]
+ if trace_sql then
+ report_state("one field with name",key)
+ end
+ p = Cg(Cc(key) * entry)
+ else
+ for i=1,n do
+ local key = keys[i]
+ if trace_sql then
+ report_state("field %s has name %q",i,key)
+ end
+ local s = Cg(Cc(key) * entry)
+ if p then
+ p = p * separator * s
+ else
+ p = s
+ end
+ end
+ end
+ p = Cf(Ct("") * p,rawset) * newline^1
+ p = skipfirst * Ct(p^0)
+ cache[first] = { parser = p, keys = keys }
+ local entries = lpegmatch(p,data)
+ return entries or { }, keys
+ end
+end
+
+local splitter = skipfirst * Ct((Ct(entry * (separator * entry)^0) * newline^1)^0)
+
+local function getdata(data)
+ return lpegmatch(splitter,data)
+end
+
+helpers.splitdata = splitdata
+helpers.getdata = getdata
+
+local function dataprepared(specification)
+ local query = preparetemplate(specification)
+ if query then
+ io.savedata(specification.queryfile,query)
+ os.remove(specification.resultfile)
+ if trace_queries then
+ report_state("query: %s",query)
+ end
+ return true
+ else
+ -- maybe push an error
+ os.remove(specification.queryfile)
+ os.remove(specification.resultfile)
+ end
+end
+
+local function datafetched(specification,runner)
+ local command = replacetemplate(runner,specification)
+ if trace_sql then
+ local t = osclock()
+ report_state("command: %s",command)
+ local okay = os.execute(command)
+ report_state("fetchtime: %.3f sec",osclock()-t) -- not okay under linux
+ return okay == 0
+ else
+ return os.execute(command) == 0
+ end
+end
+
+local function dataloaded(specification)
+ if trace_sql then
+ local t = osclock()
+ local data = io.loaddata(specification.resultfile) or ""
+ report_state("datasize: %.3f MB",#data/1024/1024)
+ report_state("loadtime: %.3f sec",osclock()-t)
+ return data
+ else
+ return io.loaddata(specification.resultfile) or ""
+ end
+end
+
+local function dataconverted(data,converter)
+ if converter then
+ local data = getdata(data)
+ if data then
+ converter.client(data)
+ end
+ return data
+ elseif trace_sql then
+ local t = osclock()
+ local data, keys = splitdata(data)
+ report_state("converttime: %.3f",osclock()-t)
+ report_state("keys: %s ",#keys)
+ report_state("entries: %s ",#data)
+ return data, keys
+ else
+ return splitdata(data)
+ end
+end
+
+-- todo: new, etc
+
+local function execute(specification)
+ if trace_sql then
+ report_state("executing client")
+ end
+ if not validspecification(specification) then
+ report_state("error in specification")
+ return
+ end
+ if not dataprepared(specification) then
+ report_state("error in preparation")
+ return
+ end
+ if not datafetched(specification,methods.client.runner) then
+ report_state("error in fetching, query: %s",string.collapsespaces(io.loaddata(specification.queryfile)))
+ return
+ end
+ local data = dataloaded(specification)
+ if not data then
+ report_state("error in loading")
+ return
+ end
+ local data, keys = dataconverted(data,specification.converter)
+ if not data then
+ report_state("error in converting")
+ return
+ end
+ local one = data[1]
+ if one then
+ setmetatable(data,{ __index = one } )
+ end
+ return data, keys
+end
+
+-- The following is not that (memory) efficient but normally we will use
+-- the lib anyway. Of course we could make a dedicated converter and/or
+-- hook into the splitter code but ... it makes not much sense because then
+-- we can as well move the builder to the library modules.
+
+local wraptemplate = [[
+local converters = utilities.sql.converters
+local deserialize = utilities.sql.deserialize
+
+local tostring = tostring
+local tonumber = tonumber
+local booleanstring = string.booleanstring
+
+%s
+
+return function(data)
+ for i=1,#data do
+ local cells = data[i]
+ data[i] = {
+ %s
+ }
+ end
+ return data
+end
+]]
+
+local celltemplate = "cells[%s]"
+
+methods.client = {
+ runner = [[mysql --batch --user="%username%" --password="%password%" --host="%host%" --port=%port% --database="%database%" --default-character-set=utf8 < "%queryfile%" > "%resultfile%"]],
+ execute = execute,
+ usesfiles = true,
+ wraptemplate = wraptemplate,
+ celltemplate = celltemplate,
+}
diff --git a/tex/context/base/util-sql-imp-library.lua b/tex/context/base/util-sql-imp-library.lua
new file mode 100644
index 000000000..f16739085
--- /dev/null
+++ b/tex/context/base/util-sql-imp-library.lua
@@ -0,0 +1,283 @@
+if not modules then modules = { } end modules ['util-sql-library'] = {
+ version = 1.001,
+ comment = "companion to util-sql.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- For some reason the sql lib partially fails in luatex when creating hashed row. So far
+-- we couldn't figure it out (some issue with adapting the table that is passes as first
+-- argument in the fetch routine. Apart from this it looks like the mysql binding has some
+-- efficiency issues (like creating a keys and types table for each row) but that could be
+-- optimized. Anyhow, fecthing results can be done as follows:
+
+-- local function collect_1(r)
+-- local t = { }
+-- for i=1,r:numrows() do
+-- t[#t+1] = r:fetch({},"a")
+-- end
+-- return t
+-- end
+--
+-- local function collect_2(r)
+-- local keys = r:getcolnames()
+-- local n = #keys
+-- local t = { }
+-- for i=1,r:numrows() do
+-- local v = { r:fetch() }
+-- local r = { }
+-- for i=1,n do
+-- r[keys[i]] = v[i]
+-- end
+-- t[#t+1] = r
+-- end
+-- return t
+-- end
+--
+-- local function collect_3(r)
+-- local keys = r:getcolnames()
+-- local n = #keys
+-- local t = { }
+-- for i=1,r:numrows() do
+-- local v = r:fetch({},"n")
+-- local r = { }
+-- for i=1,n do
+-- r[keys[i]] = v[i]
+-- end
+-- t[#t+1] = r
+-- end
+-- return t
+-- end
+--
+-- On a large table with some 8 columns (mixed text and numbers) we get the following
+-- timings (the 'a' alternative is already using the more efficient variant in the
+-- binding).
+--
+-- collect_1 : 1.31
+-- collect_2 : 1.39
+-- collect_3 : 1.75
+--
+-- Some, as a workaround for this 'bug' the second alternative can be used.
+
+local format = string.format
+local lpegmatch = lpeg.match
+local setmetatable, type = setmetatable, type
+
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql","library")
+
+local sql = require("util-sql")
+local mysql = require("luasql.mysql")
+local cache = { }
+local helpers = sql.helpers
+local methods = sql.methods
+local validspecification = helpers.validspecification
+local querysplitter = helpers.querysplitter
+local dataprepared = helpers.preparetemplate
+local serialize = sql.serialize
+local deserialize = sql.deserialize
+
+local initialize = mysql.mysql
+
+local function connect(session,specification)
+ return session:connect(
+ specification.database or "",
+ specification.username or "",
+ specification.password or "",
+ specification.host or "",
+ specification.port
+ )
+end
+
+local function datafetched(specification,query,converter)
+ if not query or query == "" then
+ report_state("no valid query")
+ return { }, { }
+ end
+ local id = specification.id
+ local session, connection
+ if id then
+ local c = cache[id]
+ if c then
+ session = c.session
+ connection = c.connection
+ end
+ if not connection then
+ session = initialize()
+ connection = connect(session,specification)
+ cache[id] = { session = session, connection = connection }
+ end
+ else
+ session = initialize()
+ connection = connect(session,specification)
+ end
+ if not connection then
+ report_state("error in connection: %s@%s to %s:%s",
+ specification.database or "no database",
+ specification.username or "no username",
+ specification.host or "no host",
+ specification.port or "no port"
+ )
+ return { }, { }
+ end
+ query = lpegmatch(querysplitter,query)
+ local result, message, okay
+ for i=1,#query do
+ local q = query[i]
+ local r, m = connection:execute(q)
+ if m then
+ report_state("error in query, stage 1: %s",string.collapsespaces(q))
+ message = message and format("%s\n%s",message,m) or m
+ end
+ local t = type(r)
+ if t == "userdata" then
+ result = r
+ okay = true
+ elseif t == "number" then
+ okay = true
+ end
+ end
+ if not okay and id then -- can go
+ if session then
+ session:close()
+ end
+ if connection then
+ connection:close()
+ end
+ session = initialize() -- maybe not needed
+ connection = connect(session,specification)
+ if connection then
+ cache[id] = { session = session, connection = connection }
+ for i=1,#query do
+ local q = query[i]
+ local r, m = connection:execute(q)
+ if m then
+ report_state("error in query, stage 2: %s",string.collapsespaces(q))
+ message = message and format("%s\n%s",message,m) or m
+ end
+ local t = type(r)
+ if t == "userdata" then
+ result = r
+ okay = true
+ elseif t == "number" then
+ okay = true
+ end
+ end
+ else
+ message = "unable to connect"
+ report_state(message)
+ end
+ end
+ local data, keys
+ if result then
+ if converter then
+ data = converter.library(result)
+ -- data = converter(result)
+ else
+ keys = result:getcolnames()
+ if keys then
+ local n = result:numrows() or 0
+ if n == 0 then
+ data = { }
+ -- elseif n == 1 then
+ -- -- data = { result:fetch({},"a") }
+ else
+ data = { }
+ -- for i=1,n do
+ -- data[i] = result:fetch({},"a")
+ -- end
+ local k = #keys
+ for i=1,n do
+ local v = { result:fetch() }
+ local d = { }
+ for i=1,k do
+ d[keys[i]] = v[i]
+ end
+ data[#data+1] = d
+ end
+ end
+ end
+ end
+ result:close()
+ elseif message then
+ report_state("message %s",message)
+ end
+ if not keys then
+ keys = { }
+ end
+ if not data then
+ data = { }
+ end
+ if not id then
+ connection:close()
+ session:close()
+ end
+ return data, keys
+end
+
+local function execute(specification)
+ if trace_sql then
+ report_state("executing library")
+ end
+ if not validspecification(specification) then
+ report_state("error in specification")
+ return
+ end
+ local query = dataprepared(specification)
+ if not query then
+ report_state("error in preparation")
+ return
+ end
+ local data, keys = datafetched(specification,query,specification.converter)
+ if not data then
+ report_state("error in fetching")
+ return
+ end
+ local one = data[1]
+ if one then
+ setmetatable(data,{ __index = one } )
+ end
+ return data, keys
+end
+
+local wraptemplate = [[
+local converters = utilities.sql.converters
+local deserialize = utilities.sql.deserialize
+
+local tostring = tostring
+local tonumber = tonumber
+local booleanstring = string.booleanstring
+
+%s
+
+return function(result)
+ if not result then
+ return { }
+ end
+ local nofrows = result:numrows() or 0
+ if nofrows == 0 then
+ return { }
+ end
+ local data = { }
+ for i=1,nofrows do
+ local cells = { result:fetch() }
+ data[i] = {
+ %s
+ }
+ end
+ return data
+end
+]]
+
+local celltemplate = "cells[%s]"
+
+methods.library = {
+ runner = function() end, -- never called
+ execute = execute,
+ initialize = initialize, -- returns session
+ usesfiles = false,
+ wraptemplate = wraptemplate,
+ celltemplate = celltemplate,
+}
diff --git a/tex/context/base/util-sql-imp-swiglib.lua b/tex/context/base/util-sql-imp-swiglib.lua
new file mode 100644
index 000000000..25723ee84
--- /dev/null
+++ b/tex/context/base/util-sql-imp-swiglib.lua
@@ -0,0 +1,426 @@
+if not modules then modules = { } end modules ['util-sql-swiglib'] = {
+ version = 1.001,
+ comment = "companion to util-sql.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- As the regular library is flawed (i.e. there are crashes in the table
+-- construction code) and also not that efficient, Luigi Scarso looked into
+-- a swig binding. This is a bit more low level approach but as we stay
+-- closer to the original library it's also less dependant.
+
+local concat = table.concat
+local format = string.format
+local lpegmatch = lpeg.match
+local setmetatable, type = setmetatable, type
+
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql","swiglib")
+
+local sql = require("util-sql")
+local mysql = require("swigluamysql")
+local cache = { }
+local helpers = sql.helpers
+local methods = sql.methods
+local validspecification = helpers.validspecification
+local querysplitter = helpers.querysplitter
+local dataprepared = helpers.preparetemplate
+local serialize = sql.serialize
+local deserialize = sql.deserialize
+
+local mysql_initialize = mysql.mysql_init
+
+local mysql_open_connection = mysql.mysql_real_connect
+local mysql_execute_query = mysql.mysql_real_query
+local mysql_close_connection = mysql.mysql_close
+
+local mysql_field_seek = mysql.mysql_field_seek
+local mysql_num_fields = mysql.mysql_num_fields
+local mysql_fetch_field = mysql.mysql_fetch_field
+local mysql_num_rows = mysql.mysql_num_rows
+local mysql_fetch_row = mysql.mysql_fetch_row
+local mysql_fetch_lengths = mysql.mysql_fetch_lengths
+local mysql_init = mysql.mysql_init
+local mysql_store_result = mysql.mysql_store_result
+local mysql_free_result = mysql.mysql_free_result
+local mysql_use_result = mysql.mysql_use_result
+
+local mysql_error_message = mysql.mysql_error
+local mysql_options_argument = mysql.mysql_options_argument
+
+local instance = mysql.MYSQL()
+
+local mysql_constant_false = mysql_options_argument(false) -- 0 "\0"
+local mysql_constant_true = mysql_options_argument(true) -- 1 "\1"
+
+-- print(swig_type(mysql_constant_false))
+-- print(swig_type(mysql_constant_true))
+
+mysql.mysql_options(instance,mysql.MYSQL_OPT_RECONNECT,mysql_constant_true);
+
+local typemap = {
+ [mysql.MYSQL_TYPE_VAR_STRING ] = "string",
+ [mysql.MYSQL_TYPE_STRING ] = "string",
+ [mysql.MYSQL_TYPE_DECIMAL ] = "number",
+ [mysql.MYSQL_TYPE_SHORT ] = "number",
+ [mysql.MYSQL_TYPE_LONG ] = "number",
+ [mysql.MYSQL_TYPE_FLOAT ] = "number",
+ [mysql.MYSQL_TYPE_DOUBLE ] = "number",
+ [mysql.MYSQL_TYPE_LONGLONG ] = "number",
+ [mysql.MYSQL_TYPE_INT24 ] = "number",
+ [mysql.MYSQL_TYPE_YEAR ] = "number",
+ [mysql.MYSQL_TYPE_TINY ] = "number",
+ [mysql.MYSQL_TYPE_TINY_BLOB ] = "binary",
+ [mysql.MYSQL_TYPE_MEDIUM_BLOB] = "binary",
+ [mysql.MYSQL_TYPE_LONG_BLOB ] = "binary",
+ [mysql.MYSQL_TYPE_BLOB ] = "binary",
+ [mysql.MYSQL_TYPE_DATE ] = "date",
+ [mysql.MYSQL_TYPE_NEWDATE ] = "date",
+ [mysql.MYSQL_TYPE_DATETIME ] = "datetime",
+ [mysql.MYSQL_TYPE_TIME ] = "time",
+ [mysql.MYSQL_TYPE_TIMESTAMP ] = "time",
+ [mysql.MYSQL_TYPE_ENUM ] = "set",
+ [mysql.MYSQL_TYPE_SET ] = "set",
+ [mysql.MYSQL_TYPE_NULL ] = "null",
+}
+
+-- real_escape_string
+
+local function finish(t)
+ mysql_free_result(t._result_)
+end
+
+-- will become metatable magic
+
+-- local function analyze(result)
+-- mysql_field_seek(result,0)
+-- local nofrows = mysql_num_rows(result) or 0
+-- local noffields = mysql_num_fields(result)
+-- local names = { }
+-- local types = { }
+-- for i=1,noffields do
+-- local field = mysql_fetch_field(result)
+-- names[i] = field.name
+-- types[i] = field.type
+-- end
+-- return names, types, noffields, nofrows
+-- end
+
+local function getcolnames(t)
+ return t.names
+end
+
+local function getcoltypes(t)
+ return t.types
+end
+
+local function numrows(t)
+ return t.nofrows
+end
+
+-- swig_type
+
+-- local ulongArray_getitem = mysql.ulongArray_getitem
+-- local util_getbytearray = mysql.util_getbytearray
+
+-- local function list(t)
+-- local result = t._result_
+-- local row = mysql_fetch_row(result)
+-- local len = mysql_fetch_lengths(result)
+-- local result = { }
+-- for i=1,t.noffields do
+-- local r = i - 1 -- zero offset
+-- result[i] = util_getbytearray(row,r,ulongArray_getitem(len,r))
+-- end
+-- return result
+-- end
+
+-- local function hash(t)
+-- local list = util_mysql_fetch_fields_from_current_row(t._result_)
+-- local result = t._result_
+-- local fields = t.names
+-- local row = mysql_fetch_row(result)
+-- local len = mysql_fetch_lengths(result)
+-- local result = { }
+-- for i=1,t.noffields do
+-- local r = i - 1 -- zero offset
+-- result[fields[i]] = util_getbytearray(row,r,ulongArray_getitem(len,r))
+-- end
+-- return result
+-- end
+
+local util_mysql_fetch_fields_from_current_row = mysql.util_mysql_fetch_fields_from_current_row
+local util_mysql_fetch_all_rows = mysql.util_mysql_fetch_all_rows
+
+local function list(t)
+ return util_mysql_fetch_fields_from_current_row(t._result_)
+end
+
+local function hash(t)
+ local list = util_mysql_fetch_fields_from_current_row(t._result_)
+ local fields = t.names
+ local data = { }
+ for i=1,t.noffields do
+ data[fields[i]] = list[i]
+ end
+ return data
+end
+
+local function wholelist(t)
+ return util_mysql_fetch_all_rows(t._result_)
+end
+
+local mt = { __index = {
+ -- regular
+ finish = finish,
+ list = list,
+ hash = hash,
+ wholelist = wholelist,
+ -- compatibility
+ numrows = numrows,
+ getcolnames = getcolnames,
+ getcoltypes = getcoltypes,
+ }
+}
+
+-- session
+
+local function close(t)
+ mysql_close_connection(t._connection_)
+end
+
+local function execute(t,query)
+ if query and query ~= "" then
+ local connection = t._connection_
+ local result = mysql_execute_query(connection,query,#query)
+ if result == 0 then
+ local result = mysql_store_result(connection)
+ mysql_field_seek(result,0)
+ local nofrows = mysql_num_rows(result) or 0
+ local noffields = mysql_num_fields(result)
+ local names = { }
+ local types = { }
+ for i=1,noffields do
+ local field = mysql_fetch_field(result)
+ names[i] = field.name
+ types[i] = field.type
+ end
+ local t = {
+ _result_ = result,
+ names = names,
+ types = types,
+ noffields = noffields,
+ nofrows = nofrows,
+ }
+ return setmetatable(t,mt)
+ end
+ end
+ return false
+end
+
+local mt = { __index = {
+ close = close,
+ execute = execute,
+ }
+}
+
+local function open(t,database,username,password,host,port)
+ local connection = mysql_open_connection(t._session_,host or "localhost",username or "",password or "",database or "",port or 0,0,0)
+ if connection then
+ local t = {
+ _connection_ = connection,
+ }
+ return setmetatable(t,mt)
+ end
+end
+
+local function message(t)
+ return mysql_error_message(t._session_)
+end
+
+local function close(t)
+ -- dummy, as we have a global session
+end
+
+local mt = {
+ __index = {
+ connect = open,
+ close = close,
+ message = message,
+ }
+}
+
+local function initialize()
+ local session = {
+ _session_ = mysql_initialize(instance) -- maybe share, single thread anyway
+ }
+ return setmetatable(session,mt)
+end
+
+-- -- -- --
+
+local function connect(session,specification)
+ return session:connect(
+ specification.database or "",
+ specification.username or "",
+ specification.password or "",
+ specification.host or "",
+ specification.port
+ )
+end
+
+local function datafetched(specification,query,converter)
+ if not query or query == "" then
+ report_state("no valid query")
+ return { }, { }
+ end
+ local id = specification.id
+ local session, connection
+ if id then
+ local c = cache[id]
+ if c then
+ session = c.session
+ connection = c.connection
+ end
+ if not connection then
+ session = initialize()
+ connection = connect(session,specification)
+ cache[id] = { session = session, connection = connection }
+ end
+ else
+ session = initialize()
+ connection = connect(session,specification)
+ end
+ if not connection then
+ report_state("error in connection: %s@%s to %s:%s",
+ specification.database or "no database",
+ specification.username or "no username",
+ specification.host or "no host",
+ specification.port or "no port"
+ )
+ return { }, { }
+ end
+ query = lpegmatch(querysplitter,query)
+ local result, message, okay
+ for i=1,#query do
+ local q = query[i]
+ local r, m = connection:execute(q)
+ if m then
+ report_state("error in query, stage: %s",string.collapsespaces(q))
+ message = message and format("%s\n%s",message,m) or m
+ end
+ if type(r) == "table" then
+ result = r
+ okay = true
+ elseif not m then
+ okay = true
+ end
+ end
+ local data, keys
+ if result then
+ if converter then
+ data = converter.swiglib(result)
+ else
+ keys = result.names
+ data = { }
+ for i=1,result.nofrows do
+ data[i] = result:hash()
+ end
+ end
+ result:finish() -- result:close()
+ elseif message then
+ report_state("message %s",message)
+ end
+ if not keys then
+ keys = { }
+ end
+ if not data then
+ data = { }
+ end
+ if not id then
+ connection:close()
+ session:close()
+ end
+ return data, keys
+end
+
+local function execute(specification)
+ if trace_sql then
+ report_state("executing library")
+ end
+ if not validspecification(specification) then
+ report_state("error in specification")
+ return
+ end
+ local query = dataprepared(specification)
+ if not query then
+ report_state("error in preparation")
+ return
+ end
+ local data, keys = datafetched(specification,query,specification.converter)
+ if not data then
+ report_state("error in fetching")
+ return
+ end
+ local one = data[1]
+ if one then
+ setmetatable(data,{ __index = one } )
+ end
+ return data, keys
+end
+
+local wraptemplate = [[
+local mysql = require("swigluamysql") -- will be stored in method
+
+----- mysql_fetch_row = mysql.mysql_fetch_row
+----- mysql_fetch_lengths = mysql.mysql_fetch_lengths
+----- util_unpackbytearray = mysql.util_unpackbytearray
+local util_mysql_fetch_fields_from_current_row
+ = mysql.util_mysql_fetch_fields_from_current_row
+
+local converters = utilities.sql.converters
+local deserialize = utilities.sql.deserialize
+
+local tostring = tostring
+local tonumber = tonumber
+local booleanstring = string.booleanstring
+
+%s
+
+return function(result)
+ if not result then
+ return { }
+ end
+ local nofrows = result.nofrows or 0
+ if nofrows == 0 then
+ return { }
+ end
+ local noffields = result.noffields or 0
+ local data = { }
+ result = result._result_
+ for i=1,nofrows do
+ -- local row = mysql_fetch_row(result)
+ -- local len = mysql_fetch_lengths(result)
+ -- local cells = util_unpackbytearray(row,noffields,len)
+ local cells = util_mysql_fetch_fields_from_current_row(result)
+ data[i] = {
+ %s
+ }
+ end
+ return data
+end
+]]
+
+local celltemplate = "cells[%s]"
+
+methods.swiglib = {
+ runner = function() end, -- never called
+ execute = execute,
+ initialize = initialize, -- returns session
+ usesfiles = false,
+ wraptemplate = wraptemplate,
+ celltemplate = celltemplate,
+}
diff --git a/tex/context/base/util-sql-loggers.lua b/tex/context/base/util-sql-loggers.lua
new file mode 100644
index 000000000..b2dccf4b5
--- /dev/null
+++ b/tex/context/base/util-sql-loggers.lua
@@ -0,0 +1,277 @@
+if not modules then modules = { } end modules ['util-sql-loggers'] = {
+ version = 1.001,
+ comment = "companion to lmx-*",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code and currently part of the base installation simply
+-- because it's easier to dirtribute this way. Eventually it will be documented
+-- and the related scripts will show up as well.
+
+local tonumber = tonumber
+local format = string.format
+local concat = table.concat
+local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime
+local random = math.random
+
+local sql = utilities.sql
+local loggers = { }
+sql.loggers = loggers
+
+local trace_sql = false trackers.register("sql.loggers.trace", function(v) trace_sql = v end)
+local report = logs.reporter("sql","loggers")
+
+loggers.newtoken = sql.tokens.new
+local makeconverter = sql.makeconverter
+
+local function checkeddb(presets,datatable)
+ return sql.usedatabase(presets,datatable or presets.datatable or "loggers")
+end
+
+loggers.usedb = checkeddb
+
+local totype = {
+ ["error"] = 1, [1] = 1, ["1"] = 1,
+ ["warning"] = 2, [2] = 2, ["2"] = 2,
+ ["debug"] = 3, [3] = 3, ["3"] = 3,
+ ["info"] = 4, [4] = 4, ["4"] = 4,
+}
+
+local fromtype = {
+ ["error"] = "error", [1] = "error", ["1"] = "error",
+ ["warning"] = "warning", [2] = "warning", ["2"] = "warning",
+ ["debug"] = "debug", [3] = "debug", ["3"] = "debug",
+ ["info"] = "info", [4] = "info", ["4"] = "info",
+}
+
+table.setmetatableindex(totype, function() return 4 end)
+table.setmetatableindex(fromtype,function() return "info" end)
+
+loggers.totype = totype
+loggers.fromtype = fromtype
+
+local template =[[
+ CREATE TABLE IF NOT EXISTS %basename% (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `time` int(11) NOT NULL,
+ `type` int(11) NOT NULL,
+ `action` varchar(15) NOT NULL,
+ `data` longtext,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `id_unique_key` (`id`)
+ )
+ DEFAULT CHARSET = utf8 ;
+]]
+
+function loggers.createdb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %q created in %q",db.name,db.base)
+
+ return db
+
+end
+
+local template =[[
+ DROP TABLE IF EXISTS %basename% ;
+]]
+
+function loggers.deletedb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %q removed in %q",db.name,db.base)
+
+end
+
+local template =[[
+ INSERT INTO %basename% (
+ `time`,
+ `type`,
+ `action`,
+ `data`
+ ) VALUES (
+ %time%,
+ %type%,
+ '%action%',
+ '%[data]%'
+ ) ;
+]]
+
+function loggers.save(db,data) -- beware, we pass type and action in the data (saves a table)
+
+ if data then
+
+ local time = ostime()
+ local kind = totype[data.type]
+ local action = data.action or "unknown"
+
+ data.type = nil
+ data.action = nil
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ time = ostime(),
+ type = kind,
+ action = action,
+ data = data and db.serialize(data,"return") or "",
+ },
+ }
+
+ end
+
+end
+
+-- local template =[[
+-- REMOVE FROM
+-- %basename%
+-- WHERE
+-- `token` = '%token%' ;
+-- ]]
+--
+-- function loggers.remove(db,token)
+--
+-- db.execute {
+-- template = template,
+-- variables = {
+-- basename = db.basename,
+-- token = token,
+-- },
+-- }
+--
+-- if trace_sql then
+-- report("removed: %s",token)
+-- end
+--
+-- end
+
+local template_nop =[[
+ SELECT
+ `time`,
+ `type`,
+ `action`,
+ `data`
+ FROM
+ %basename%
+ ORDER BY
+ `time`, `type`, `action`
+ DESC LIMIT
+ %limit% ;
+]]
+
+local template_yes =[[
+ SELECT
+ `time`,
+ `type`,
+ `action`,
+ `data`
+ FROM
+ %basename%
+ %WHERE%
+ ORDER BY
+ `time`, `type`, `action`
+ DESC LIMIT
+ %limit% ;
+]]
+
+local converter = makeconverter {
+ -- { name = "time", type = os.localtime },
+ { name = "time", type = "number" },
+ { name = "type", type = fromtype },
+ { name = "action", type = "string" },
+ { name = "data", type = "deserialize" },
+}
+
+function loggers.collect(db,specification)
+
+ specification = specification or { }
+
+ local start = specification.start
+ local stop = specification.stop
+ local limit = specification.limit or 100
+ local kind = specification.type
+ local action = specification.action
+
+ local filtered = start or stop
+
+ local where = { }
+
+ if filtered then
+ local today = os.date("*t")
+
+ if type(start) ~= "table" then
+ start = { }
+ end
+ start = os.time {
+ day = start.day or today.day,
+ month = start.month or today.month,
+ year = start.year or today.year,
+ hour = start.hour or 0,
+ minute = start.minute or 0,
+ second = start.second or 0,
+ isdst = true,
+ }
+
+ if type(stop) ~= "table" then
+ stop = { }
+ end
+ stop = os.time {
+ day = stop.day or today.day,
+ month = stop.month or today.month,
+ year = stop.year or today.year,
+ hour = stop.hour or 24,
+ minute = stop.minute or 0,
+ second = stop.second or 0,
+ isdst = true,
+ }
+
+ -- report("filter: %s => %s",start,stop)
+
+ where[#where+1] = format("`time` BETWEEN %s AND %s",start,stop)
+
+ end
+
+ if kind then
+ where[#where+1] = format("`type` = %s",totype[kind])
+ end
+
+ if action then
+ where[#where+1] = format("`action` = '%s'",action)
+ end
+
+ local records = db.execute {
+ template = filtered and template_yes or template_nop,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ limit = limit,
+ WHERE = #where > 0 and format("WHERE\n%s",concat(where," AND ")) or "",
+ },
+ }
+
+ if trace_sql then
+ report("collected: %s loggers",#records)
+ end
+
+ return records, keys
+
+end
diff --git a/tex/context/base/util-sql-sessions.lua b/tex/context/base/util-sql-sessions.lua
new file mode 100644
index 000000000..40556dd5e
--- /dev/null
+++ b/tex/context/base/util-sql-sessions.lua
@@ -0,0 +1,349 @@
+if not modules then modules = { } end modules ['util-sql-sessions'] = {
+ version = 1.001,
+ comment = "companion to lmx-*",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code and currently part of the base installation simply
+-- because it's easier to dirtribute this way. Eventually it will be documented
+-- and the related scripts will show up as well.
+
+-- maybe store threshold in session (in seconds)
+
+local tonumber = tonumber
+local format = string.format
+local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime
+local random = math.random
+
+-- In older frameworks we kept a session table in memory. This time we
+-- follow a route where we store session data in a sql table. Each session
+-- has a token (similar to what we do on q2p and pod services), a data
+-- blob which is just a serialized lua table (we could consider a dump instead)
+-- and two times: the creation and last accessed time. The first one is handy
+-- for statistics and the second one for cleanup. Both are just numbers so that
+-- we don't have to waste code on conversions. Anyhow, we provide variants so that
+-- we can always choose what is best.
+
+local sql = utilities.sql
+local sessions = { }
+sql.sessions = sessions
+
+local trace_sql = false trackers.register("sql.sessions.trace", function(v) trace_sql = v end)
+local report = logs.reporter("sql","sessions")
+
+sessions.newtoken = sql.tokens.new
+
+local function checkeddb(presets,datatable)
+ return sql.usedatabase(presets,datatable or presets.datatable or "sessions")
+end
+
+sessions.usedb = checkeddb
+
+local template =[[
+ CREATE TABLE IF NOT EXISTS %basename% (
+ `token` varchar(50) NOT NULL,
+ `data` longtext NOT NULL,
+ `created` int(11) NOT NULL,
+ `accessed` int(11) NOT NULL,
+ UNIQUE KEY `token_unique_key` (`token`)
+ )
+ DEFAULT CHARSET = utf8 ;
+]]
+
+function sessions.createdb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %q created in %q",db.name,db.base)
+
+ return db
+
+end
+
+local template =[[
+ DROP TABLE IF EXISTS %basename% ;
+]]
+
+function sessions.deletedb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %q removed in %q",db.name,db.base)
+
+end
+
+local template =[[
+ INSERT INTO %basename% (
+ `token`,
+ `created`,
+ `accessed`,
+ `data`
+ ) VALUES (
+ '%token%',
+ %time%,
+ %time%,
+ '%[data]%'
+ ) ;
+]]
+
+function sessions.create(db,data)
+
+ local token = sessions.newtoken()
+ local time = ostime()
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ time = time,
+ data = db.serialize(data or { },"return")
+ },
+ }
+
+ if trace_sql then
+ report("created: %s at %s",token,osfulltime(time))
+ end
+
+ return {
+ token = token,
+ created = time,
+ accessed = time,
+ data = data,
+ }
+end
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `data` = '%[data]%',
+ `accessed` = %time%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function sessions.save(db,session)
+
+ local time = ostime()
+ local data = db.serialize(session.data or { },"return")
+ local token = session.token
+
+ session.accessed = time
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ time = ostime(),
+ data = data,
+ },
+ }
+
+ if trace_sql then
+ report("saved: %s at %s",token,osfulltime(time))
+ end
+
+ return session
+end
+
+local template = [[
+ UPDATE
+ %basename%
+ SET
+ `accessed` = %time%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function sessions.touch(db,token)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ time = ostime(),
+ },
+ }
+
+end
+
+local template = [[
+ UPDATE
+ %basename%
+ SET
+ `accessed` = %time%
+ WHERE
+ `token` = '%token%' ;
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function sessions.restore(db,token)
+
+ local records, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ time = ostime(),
+ },
+ }
+
+ local record = records and records[1]
+
+ if record then
+ if trace_sql then
+ report("restored: %s",token)
+ end
+ record.data = db.deserialize(record.data or "")
+ return record, keys
+ elseif trace_sql then
+ report("unknown: %s",token)
+ end
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function sessions.remove(db,token)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ },
+ }
+
+ if trace_sql then
+ report("removed: %s",token)
+ end
+
+end
+
+local template_collect_yes =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ ORDER BY
+ `created` ;
+]]
+
+local template_collect_nop =[[
+ SELECT
+ `accessed`,
+ `created`,
+ `accessed`,
+ `token`
+ FROM
+ %basename%
+ ORDER BY
+ `created` ;
+]]
+
+function sessions.collect(db,nodata)
+
+ local records, keys = db.execute {
+ template = nodata and template_collect_nop or template_collect_yes,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ if not nodata then
+ db.unpackdata(records)
+ end
+
+ if trace_sql then
+ report("collected: %s sessions",#records)
+ end
+
+ return records, keys
+
+end
+
+local template_cleanup_yes =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `accessed` < %time%
+ ORDER BY
+ `created` ;
+ DELETE FROM
+ %basename%
+ WHERE
+ `accessed` < %time% ;
+]]
+
+local template_cleanup_nop =[[
+ SELECT
+ `accessed`,
+ `created`,
+ `accessed`,
+ `token`
+ FROM
+ %basename%
+ WHERE
+ `accessed` < %time%
+ ORDER BY
+ `created` ;
+ DELETE FROM
+ %basename%
+ WHERE
+ `accessed` < %time% ;
+]]
+
+function sessions.cleanupdb(db,delta,nodata)
+
+ local time = ostime()
+
+ local records, keys = db.execute {
+ template = nodata and template_cleanup_nop or template_cleanup_yes,
+ variables = {
+ basename = db.basename,
+ time = time - delta
+ },
+ }
+
+ if not nodata then
+ db.unpackdata(records)
+ end
+
+ if trace_sql then
+ report("cleaned: %s seconds before %s",delta,osfulltime(time))
+ end
+
+ return records, keys
+
+end
diff --git a/tex/context/base/util-sql-tickets.lua b/tex/context/base/util-sql-tickets.lua
new file mode 100644
index 000000000..1dfe1e376
--- /dev/null
+++ b/tex/context/base/util-sql-tickets.lua
@@ -0,0 +1,698 @@
+if not modules then modules = { } end modules ['util-sql-tickets'] = {
+ version = 1.001,
+ comment = "companion to lmx-*",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code and currently part of the base installation simply
+-- because it's easier to dirtribute this way. Eventually it will be documented
+-- and the related scripts will show up as well.
+
+local tonumber = tonumber
+local format = string.format
+local ostime, uuid, osfulltime = os.time, os.uuid, os.fulltime
+local random = math.random
+local concat = table.concat
+
+local sql = utilities.sql
+local tickets = { }
+sql.tickets = tickets
+
+local trace_sql = false trackers.register("sql.tickets.trace", function(v) trace_sql = v end)
+local report = logs.reporter("sql","tickets")
+
+local serialize = sql.serialize
+local deserialize = sql.deserialize
+local execute = sql.execute
+
+tickets.newtoken = sql.tokens.new
+
+local statustags = { [0] = -- beware index can be string or number, maybe status should be a string in the database
+ "unknown",
+ "pending",
+ "busy",
+ "finished",
+ "error",
+ "deleted",
+}
+
+local status = table.swapped(statustags)
+
+tickets.status = status
+tickets.statustags = statustags
+
+local function checkeddb(presets,datatable)
+ return sql.usedatabase(presets,datatable or presets.datatable or "tickets")
+end
+
+tickets.usedb = checkeddb
+
+local template =[[
+ CREATE TABLE IF NOT EXISTS %basename% (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `token` varchar(50) NOT NULL,
+ `subtoken` INT(11) NOT NULL,
+ `created` int(11) NOT NULL,
+ `accessed` int(11) NOT NULL,
+ `category` int(11) NOT NULL,
+ `status` int(11) NOT NULL,
+ `usertoken` varchar(50) NOT NULL,
+ `data` longtext NOT NULL,
+ `comment` longtext NOT NULL,
+
+ PRIMARY KEY (`id`),
+ UNIQUE INDEX `id_unique_index` (`id` ASC),
+ KEY `token_unique_key` (`token`)
+ )
+ DEFAULT CHARSET = utf8 ;
+]]
+
+function tickets.createdb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ local data, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %q created in %q",db.name,db.base)
+
+ return db
+
+end
+
+local template =[[
+ DROP TABLE IF EXISTS %basename% ;
+]]
+
+function tickets.deletedb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ local data, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %q removed in %q",db.name,db.base)
+
+end
+
+local template =[[
+ LOCK TABLES
+ %basename%
+ WRITE ;
+ INSERT INTO %basename% (
+ `token`,
+ `subtoken`,
+ `created`,
+ `accessed`,
+ `status`,
+ `category`,
+ `usertoken`,
+ `data`,
+ `comment`
+ ) VALUES (
+ '%token%',
+ %subtoken%,
+ %time%,
+ %time%,
+ %status%,
+ %category%,
+ '%usertoken%',
+ '%[data]%',
+ '%[comment]%'
+ ) ;
+ SELECT
+ LAST_INSERT_ID() AS `id` ;
+ UNLOCK TABLES ;
+]]
+
+function tickets.create(db,ticket)
+
+ local token = ticket.token or tickets.newtoken()
+ local time = ostime()
+ local status = ticket.status or 0
+ local category = ticket.category or 0
+ local subtoken = ticket.subtoken or 0
+ local usertoken = ticket.usertoken or ""
+ local comment = ticket.comment or ""
+
+ local result, message = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ subtoken = subtoken,
+ time = time,
+ status = status,
+ category = category,
+ usertoken = usertoken,
+ data = db.serialize(ticket.data or { },"return"),
+ comment = comment,
+ },
+ }
+
+ if trace_sql then
+ report("created: %s at %s",token,osfulltime(time))
+ end
+
+ local id = result and result.id
+
+ if id then
+
+ return {
+ id = id,
+ token = token,
+ subtoken = subtoken,
+ created = time,
+ accessed = time,
+ status = status,
+ category = category,
+ usertoken = usertoken,
+ data = data,
+ comment = comment,
+ }
+
+ end
+end
+
+local template =[[
+ LOCK TABLES
+ %basename%
+ WRITE ;
+ UPDATE %basename% SET
+ `data` = '%[data]%',
+ `status` = %status%,
+ `accessed` = %time%
+ WHERE
+ `id` = %id% ;
+ UNLOCK TABLES ;
+]]
+
+function tickets.save(db,ticket)
+
+ local time = ostime()
+ local data = db.serialize(ticket.data or { },"return")
+ local status = ticket.status or 0
+ local id = ticket.id
+
+ if not status then
+ status = 0
+ ticket.status = 0
+ end
+
+ ticket.accessed = time
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ time = ostime(),
+ status = status,
+ data = data,
+ },
+ }
+
+ if trace_sql then
+ report("saved: id %s, time %s",id,osfulltime(time))
+ end
+
+ return ticket
+end
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `accessed` = %time%
+ WHERE
+ `token` = '%token%' ;
+
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `id` = %id% ;
+]]
+
+function tickets.restore(db,id)
+
+ local record, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ time = ostime(),
+ },
+ }
+
+ local record = record and record[1]
+
+ if record then
+ if trace_sql then
+ report("restored: id %s",id)
+ end
+ record.data = db.deserialize(record.data or "")
+ return record
+ elseif trace_sql then
+ report("unknown: id %s",id)
+ end
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `id` = %id% ;
+]]
+
+function tickets.remove(db,id)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ },
+ }
+
+ if trace_sql then
+ report("removed: id %s",id)
+ end
+
+end
+
+local template_yes =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ ORDER BY
+ `created` ;
+]]
+
+local template_nop =[[
+ SELECT
+ `created`,
+ `usertoken`,
+ `accessed`,
+ `status`
+ FROM
+ %basename%
+ ORDER BY
+ `created` ;
+]]
+
+function tickets.collect(db,nodata)
+
+ local records, keys = db.execute {
+ template = nodata and template_nop or template_yes,
+ variables = {
+ basename = db.basename,
+ token = token,
+ },
+ }
+
+ if not nodata then
+ db.unpackdata(records)
+ end
+
+ if trace_sql then
+ report("collected: %s tickets",#records)
+ end
+
+ return records, keys
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `accessed` < %time% OR `status` = 5 ;
+]]
+
+local template_cleanup_yes =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `accessed` < %time%
+ ORDER BY
+ `created` ;
+ DELETE FROM
+ %basename%
+ WHERE
+ `accessed` < %time% OR `status` = 5 ;
+]]
+
+local template_cleanup_nop =[[
+ SELECT
+ `accessed`,
+ `created`,
+ `accessed`,
+ `token`
+ `usertoken`
+ FROM
+ %basename%
+ WHERE
+ `accessed` < %time%
+ ORDER BY
+ `created` ;
+ DELETE FROM
+ %basename%
+ WHERE
+ `accessed` < %time% OR `status` = 5 ;
+]]
+
+function tickets.cleanupdb(db,delta,nodata) -- maybe delta in db
+
+ local time = delta and (ostime() - delta) or 0
+
+ local records, keys = db.execute {
+ template = nodata and template_cleanup_nop or template_cleanup_yes,
+ variables = {
+ basename = db.basename,
+ time = time,
+ },
+ }
+
+ if not nodata then
+ db.unpackdata(records)
+ end
+
+ if trace_sql then
+ report("cleaned: %s seconds before %s",delta,osfulltime(time))
+ end
+
+ return records, keys
+
+end
+
+-- status related functions
+
+local template =[[
+ SELECT
+ `status`
+ FROM
+ %basename%
+ WHERE
+ `token` = '%token%' ;
+]]
+
+function tickets.getstatus(db,token)
+
+ local record, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ token = token,
+ },
+ }
+
+ local record = record and record[1]
+
+ return record and record.status or 0
+
+end
+
+local template =[[
+ SELECT
+ `status`
+ FROM
+ %basename%
+ WHERE
+ `status` = 5 OR `accessed` < %time% ;
+]]
+
+function tickets.getobsolete(db,delta)
+
+ local time = delta and (ostime() - delta) or 0
+
+ local records = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ time = time,
+ },
+ }
+
+ db.unpackdata(records)
+
+ return records
+
+end
+
+local template =[[
+ SELECT
+ `id`
+ FROM
+ %basename%
+ WHERE
+ `status` = %status%
+ LIMIT
+ 1 ;
+]]
+
+function tickets.hasstatus(db,status)
+
+ local record = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ status = status or 0,
+ },
+ }
+
+ return record and #record > 0 or false
+
+end
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `status` = %status%,
+ `accessed` = %time%
+ WHERE
+ `id` = %id% ;
+]]
+
+function tickets.setstatus(db,id,status)
+
+ local record, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ time = ostime(),
+ status = status or 0,
+ },
+ }
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `status` IN (%status%) ;
+]]
+
+function tickets.prunedb(db,status)
+
+ if type(status) == "table" then
+ status = concat(status,",")
+ end
+
+ local data, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ status = status or 0,
+ },
+ }
+
+ if trace_sql then
+ report("pruned: status %s removed",status)
+ end
+
+end
+
+local template_a = [[
+ LOCK TABLES
+ %basename%
+ WRITE ;
+ SET
+ @first_token = "?" ;
+ SELECT
+ `token`
+ INTO
+ @first_token
+ FROM
+ %basename%
+ WHERE
+ `status` = %status%
+ ORDER BY
+ `id`
+ LIMIT 1 ;
+ UPDATE
+ %basename%
+ SET
+ `status` = %newstatus%,
+ `accessed` = %time%
+ WHERE
+ `token` = @first_token ;
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `token` = @first_token
+ ORDER BY
+ `id` ;
+ UNLOCK TABLES ;
+]]
+
+local template_b = [[
+ SET
+ @first_token = "?" ;
+ SELECT
+ `token`
+ INTO
+ @first_token
+ FROM
+ %basename%
+ WHERE
+ `status` = %status%
+ ORDER BY
+ `id`
+ LIMIT 1 ;
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `token` = @first_token
+ ORDER BY
+ `id` ;
+]]
+
+function tickets.getfirstwithstatus(db,status,newstatus)
+
+ local records
+
+ if type(newstatus) == "number" then
+
+ records = db.execute {
+ template = template_a,
+ variables = {
+ basename = db.basename,
+ status = status or 0,
+ newstatus = newstatus,
+ time = ostime(),
+ },
+ }
+
+
+ else
+
+ records = db.execute {
+ template = template_b,
+ variables = {
+ basename = db.basename,
+ status = status or 0,
+ },
+ }
+
+ end
+
+ if type(records) == "table" and #records > 0 then
+
+ for i=1,#records do
+ local record = records[i]
+ record.data = db.deserialize(record.data or "")
+ record.status = newstatus
+ end
+
+ return records
+
+ end
+end
+
+local template =[[
+ SELECT
+ *
+ FROM
+ %basename%
+ WHERE
+ `usertoken` = '%usertoken%' AND `status` != 5
+ ORDER BY
+ `created` ;
+]]
+
+function tickets.getusertickets(db,usertoken)
+
+ -- todo: update accessed
+ -- todo: get less fields
+ -- maybe only data for status changed (hard to check)
+
+ local records, keys = db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ usertoken = usertoken,
+ },
+ }
+
+ db.unpackdata(records)
+
+ return records
+
+end
+
+local template =[[
+ LOCK TABLES
+ %basename%
+ WRITE ;
+ UPDATE %basename% SET
+ `status` = 5
+ WHERE
+ `usertoken` = '%usertoken%' ;
+ UNLOCK TABLES ;
+]]
+
+function tickets.removeusertickets(db,usertoken)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ usertoken = usertoken,
+ },
+ }
+
+ if trace_sql then
+ report("removed: usertoken %s",usertoken)
+ end
+
+end
+
+-- -- left-overs --
+
+-- LOCK TABLES `m4alltickets` WRITE ;
+-- CREATE TEMPORARY TABLE ticketset SELECT * FROM m4alltickets WHERE token = @first_token ;
+-- DROP TABLE ticketset ;
+-- UNLOCK TABLES ;
diff --git a/tex/context/base/util-sql-users.lua b/tex/context/base/util-sql-users.lua
new file mode 100644
index 000000000..8147f532d
--- /dev/null
+++ b/tex/context/base/util-sql-users.lua
@@ -0,0 +1,391 @@
+if not modules then modules = { } end modules ['util-sql-users'] = {
+ version = 1.001,
+ comment = "companion to lmx-*",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code and currently part of the base installation simply
+-- because it's easier to dirtribute this way. Eventually it will be documented
+-- and the related scripts will show up as well.
+
+local sql = require("util-sql")
+local md5 = require("md5")
+
+local format, upper, find, gsub, escapedpattern = string.format, string.upper, string.find, string.gsub, string.escapedpattern
+local sumhexa = md5.sumhexa
+local booleanstring = string.booleanstring
+
+local users = { }
+sql.users = users
+
+local trace_sql = false trackers.register("sql.users.trace", function(v) trace_sql = v end)
+local report = logs.reporter("sql","users")
+
+local function encryptpassword(str)
+ if not str or str == "" then
+ return ""
+ elseif find(str,"^MD5:") then
+ return str
+ else
+ return upper(format("MD5:%s",sumhexa(str)))
+ end
+end
+
+local function cleanuppassword(str)
+ return (gsub(str,"^MD5:",""))
+end
+
+local function samepasswords(one,two)
+ if not one or not two then
+ return false
+ end
+ if not find(one,"^MD5:") then
+ one = encryptpassword(one)
+ end
+ if not find(two,"^MD5:") then
+ two = encryptpassword(two)
+ end
+ return one == two
+end
+
+local function validaddress(address,addresses)
+ if address and addresses and address ~= "" and addresses ~= "" then
+ if find(address,"^" .. escapedpattern(addresses,true)) then -- simple escapes
+ return true, "valid remote address"
+ end
+ return false, "invalid remote address"
+ else
+ return true, "no remote address check"
+ end
+end
+
+
+users.encryptpassword = encryptpassword
+users.cleanuppassword = cleanuppassword
+users.samepasswords = samepasswords
+users.validaddress = validaddress
+
+-- print(users.encryptpassword("test")) -- MD5:098F6BCD4621D373CADE4E832627B4F6
+
+local function checkeddb(presets,datatable)
+ return sql.usedatabase(presets,datatable or presets.datatable or "users")
+end
+
+users.usedb = checkeddb
+
+local groupnames = { }
+local groupnumbers = { }
+
+local function registergroup(name)
+ local n = #groupnames + 1
+ groupnames [n] = name
+ groupnames [tostring(n)] = name
+ groupnames [name] = name
+ groupnumbers[n] = n
+ groupnumbers[tostring(n)] = n
+ groupnumbers[name] = n
+ return n
+end
+
+registergroup("superuser")
+registergroup("administrator")
+registergroup("user")
+registergroup("guest")
+
+users.groupnames = groupnames
+users.groupnumbers = groupnumbers
+
+-- password 'test':
+--
+-- INSERT insert into users (`name`,`password`,`group`,`enabled`) values ('...','MD5:098F6BCD4621D373CADE4E832627B4F6',1,1) ;
+
+local template =[[
+ CREATE TABLE `users` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(80) NOT NULL,
+ `password` varchar(50) DEFAULT NULL,
+ `group` int(11) NOT NULL,
+ `enabled` int(11) DEFAULT '1',
+ `email` varchar(80) DEFAULT NULL,
+ `address` varchar(256) DEFAULT NULL,
+ `data` longtext,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name_unique` (`name`)
+ ) DEFAULT CHARSET = utf8 ;
+]]
+
+local converter, fields = sql.makeconverter {
+ { name = "id", type = "number" },
+ { name = "name", type = "string" },
+ { name = "password", type = "string" },
+ { name = "group", type = groupnames },
+ { name = "enabled", type = "boolean" },
+ { name = "email", type = "string" },
+ { name = "address", type = "string" },
+ { name = "data", type = "deserialize" },
+}
+
+function users.createdb(presets,datatable)
+
+ local db = checkeddb(presets,datatable)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ },
+ }
+
+ report("datatable %q created in %q",db.name,db.base)
+
+ return db
+
+end
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ WHERE
+ `name` = '%name%'
+ AND
+ `password` = '%password%'
+ ;
+]]
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ WHERE
+ `name` = '%name%'
+ ;
+]]
+
+function users.valid(db,username,password,address)
+
+ local data = db.execute {
+ template = template,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ fields = fields,
+ name = username,
+ },
+ }
+
+ local data = data and data[1]
+
+ if not data then
+ return false, "unknown user"
+ elseif not data.enabled then
+ return false, "disabled user"
+ elseif data.password ~= encryptpassword(password) then
+ return false, "wrong password"
+ elseif not validaddress(address,data.address) then
+ return false, "invalid address"
+ else
+ data.password = nil
+ return data, "okay"
+ end
+
+end
+
+local template =[[
+ INSERT INTO %basename% (
+ `name`,
+ `password`,
+ `group`,
+ `enabled`,
+ `email`,
+ `address`,
+ `data`
+ ) VALUES (
+ '%name%',
+ '%password%',
+ '%group%',
+ '%enabled%',
+ '%email%',
+ '%address%',
+ '%[data]%'
+ ) ;
+]]
+
+function users.add(db,specification)
+
+ local name = specification.username or specification.name
+
+ if not name or name == "" then
+ return
+ end
+
+ local data = specification.data
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ name = name,
+ password = encryptpassword(specification.password or ""),
+ group = groupnumbers[specification.group] or groupnumbers.guest,
+ enabled = booleanstring(specification.enabled) and "1" or "0",
+ email = specification.email,
+ address = specification.address,
+ data = type(data) == "table" and db.serialize(data,"return") or "",
+ },
+ }
+
+end
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ WHERE
+ `name` = '%name%' ;
+]]
+
+function users.getbyname(db,name)
+
+ local data = db.execute {
+ template = template,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ fields = fields,
+ name = name,
+ },
+ }
+
+ return data and data[1] or nil
+
+end
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ WHERE
+ `id` = '%id%' ;
+]]
+
+local function getbyid(db,id)
+
+ local data = db.execute {
+ template = template,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ fields = fields,
+ id = id,
+ },
+ }
+
+ return data and data[1] or nil
+
+end
+
+users.getbyid = getbyid
+
+local template =[[
+ UPDATE
+ %basename%
+ SET
+ `password` = '%password%',
+ `group` = '%group%',
+ `enabled` = '%enabled%',
+ `email` = '%email%',
+ `address` = '%address%',
+ `data` = '%[data]%'
+ WHERE
+ `id` = '%id%'
+ ;
+]]
+
+function users.save(db,id,specification)
+
+ if not tonumber(id) then
+ return
+ end
+
+ local user = getbyid(db,id)
+
+ if user.id ~= id then
+ return
+ end
+
+ local password = specification.password == nil and user.password or specification.password
+ local group = specification.group == nil and user.group or specification.group
+ local enabled = specification.enabled == nil and user.enabled or specification.enabled
+ local email = specification.email == nil and user.email or specification.email
+ local address = specification.address == nil and user.address or specification.address
+ local data = specification.data == nil and user.data or specification.data
+
+-- table.print(data)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ password = encryptpassword(password),
+ group = groupnumbers[group],
+ enabled = booleanstring(enabled) and "1" or "0",
+ email = email,
+ address = address,
+ data = type(data) == "table" and db.serialize(data,"return") or "",
+ },
+ }
+
+ return getbyid(db,id)
+
+end
+
+local template =[[
+ DELETE FROM
+ %basename%
+ WHERE
+ `id` = '%id%' ;
+]]
+
+function users.remove(db,id)
+
+ db.execute {
+ template = template,
+ variables = {
+ basename = db.basename,
+ id = id,
+ },
+ }
+
+end
+
+local template =[[
+ SELECT
+ %fields%
+ FROM
+ %basename%
+ ORDER BY
+ `name` ;
+]]
+
+function users.collect(db) -- maybe also an id/name only variant
+
+ local records, keys = db.execute {
+ template = template,
+ converter = converter,
+ variables = {
+ basename = db.basename,
+ fields = fields,
+ },
+ }
+
+ return records, keys
+
+end
diff --git a/tex/context/base/util-sql.lua b/tex/context/base/util-sql.lua
new file mode 100644
index 000000000..70c7d4be6
--- /dev/null
+++ b/tex/context/base/util-sql.lua
@@ -0,0 +1,425 @@
+if not modules then modules = { } end modules ['util-sql'] = {
+ version = 1.001,
+ comment = "companion to m-sql.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Of course we could use a library but we don't want another depedency and there is
+-- a bit of flux in these libraries. Also, we want the data back in a way that we
+-- like.
+--
+-- This is the first of set of sql related modules that are providing functionality
+-- for a web based framework that we use for typesetting (related) services. We're
+-- talking of session management, job ticket processing, storage, (xml) file processing
+-- and dealing with data from databases (often ambitiously called database publishing).
+--
+-- There is no generic solution for such services, but from our perspective, as we use
+-- context in a regular tds tree (the standard distribution) it makes sense to put shared
+-- code in the context distribution. That way we don't need to reinvent wheels every time.
+
+-- We use the template mechanism from util-tpl which inturn is just using the dos cq
+-- windows convention of %whatever% variables that I've used for ages.
+
+-- util-sql-imp-client.lua
+-- util-sql-imp-library.lua
+-- util-sql-imp-swiglib.lua
+-- util-sql-imp-lmxsql.lua
+
+-- local sql = require("util-sql")
+--
+-- local converter = sql.makeconverter {
+-- { name = "id", type = "number" },
+-- { name = "data",type = "string" },
+-- }
+--
+-- local execute = sql.methods.swiglib.execute
+-- -- local execute = sql.methods.library.execute
+-- -- local execute = sql.methods.client.execute
+-- -- local execute = sql.methods.lmxsql.execute
+--
+-- result = execute {
+-- presets = {
+-- host = "localhost",
+-- username = "root",
+-- password = "test",
+-- database = "test",
+-- id = "test", -- forces persistent session
+-- },
+-- template = "select * from `test` where `id` > %criterium% ;",
+-- variables = {
+-- criterium = 2,
+-- },
+-- converter = converter
+-- }
+--
+-- inspect(result)
+
+local format, match = string.format, string.match
+local random = math.random
+local rawset, setmetatable, getmetatable, loadstring, type = rawset, setmetatable, getmetatable, loadstring, type
+local P, S, V, C, Cs, Ct, Cc, Cg, Cf, patterns, lpegmatch = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.patterns, lpeg.match
+local concat = table.concat
+
+local osuuid = os.uuid
+local osclock = os.clock or os.time
+local ostime = os.time
+
+local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
+local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
+local report_state = logs.reporter("sql")
+
+-- trace_sql = true
+-- trace_queries = true
+
+utilities.sql = utilities.sql or { }
+local sql = utilities.sql
+
+local replacetemplate = utilities.templates.replace
+local loadtemplate = utilities.templates.load
+
+local methods = { }
+sql.methods = methods
+
+local helpers = { }
+sql.helpers = helpers
+
+local serialize = table.fastserialize
+local deserialize = table.deserialize
+
+sql.serialize = serialize
+sql.deserialize = deserialize
+
+helpers.serialize = serialize -- bonus
+helpers.deserialize = deserialize -- bonus
+
+local defaults = { __index =
+ {
+ resultfile = "result.dat",
+ templatefile = "template.sql",
+ queryfile = "query.sql",
+ variables = { },
+ username = "default",
+ password = "default",
+ host = "localhost",
+ port = 3306,
+ database = "default",
+ },
+}
+
+table.setmetatableindex(sql.methods,function(t,k)
+ require("util-sql-imp-"..k)
+ return rawget(t,k)
+end)
+
+-- converters
+
+local converters = { }
+sql.converters = converters
+
+local function makeconverter(entries,celltemplate,wraptemplate)
+ local shortcuts = { }
+ local assignments = { }
+ local function cell(i)
+ return format(celltemplate,i,i)
+ end
+ for i=1,#entries do
+ local entry = entries[i]
+ local nam = entry.name
+ local typ = entry.type
+ if typ == "boolean" then
+ assignments[i] = format("[%q] = booleanstring(%s),",nam,cell(i))
+ elseif typ == "number" then
+ assignments[i] = format("[%q] = tonumber(%s),",nam,cell(i))
+ elseif type(typ) == "function" then
+ local c = #converters + 1
+ converters[c] = typ
+ shortcuts[#shortcuts+1] = format("local fun_%s = converters[%s]",c,c)
+ assignments[i] = format("[%q] = fun_%s(%s),",nam,c,cell(i))
+ elseif type(typ) == "table" then
+ local c = #converters + 1
+ converters[c] = typ
+ shortcuts[#shortcuts+1] = format("local tab_%s = converters[%s]",c,c)
+ assignments[i] = format("[%q] = tab_%s[%s],",nam,#converters,cell(i))
+ elseif typ == "deserialize" then
+ assignments[i] = format("[%q] = deserialize(%s),",nam,cell(i))
+ else
+ assignments[i] = format("[%q] = %s,",nam,cell(i))
+ end
+ end
+ local code = format(wraptemplate,concat(shortcuts,"\n"),concat(assignments,"\n "))
+ local func = loadstring(code)
+ return func and func()
+end
+
+function sql.makeconverter(entries)
+ local fields = { }
+ for i=1,#entries do
+ fields[i] = format("`%s`",entries[i].name)
+ end
+ fields = concat(fields, ", ")
+ local converter = {
+ fields = fields
+ }
+ table.setmetatableindex(converter, function(t,k)
+ local sqlmethod = methods[k]
+ local v = makeconverter(entries,sqlmethod.celltemplate,sqlmethod.wraptemplate)
+ t[k] = v
+ return v
+ end)
+ return converter, fields
+end
+
+-- helper for libraries:
+
+local function validspecification(specification)
+ local presets = specification.presets
+ if type(presets) == "string" then
+ presets = dofile(presets)
+ end
+ if type(presets) == "table" then
+ setmetatable(presets,defaults)
+ setmetatable(specification,{ __index = presets })
+ else
+ setmetatable(specification,defaults)
+ end
+ return true
+end
+
+helpers.validspecification = validspecification
+
+local whitespace = patterns.whitespace^0
+local eol = patterns.eol
+local separator = P(";")
+local escaped = patterns.escaped
+local dquote = patterns.dquote
+local squote = patterns.squote
+local dsquote = squote * squote
+---- quoted = patterns.quoted
+local quoted = dquote * (escaped + (1-dquote))^0 * dquote
+ + squote * (escaped + dsquote + (1-squote))^0 * squote
+local comment = P("--") * (1-eol) / ""
+local query = whitespace
+ * Cs((quoted + comment + 1 - separator)^1 * Cc(";"))
+ * whitespace
+local splitter = Ct(query * (separator * query)^0)
+
+helpers.querysplitter = splitter
+
+-- I will add a bit more checking.
+
+local function validspecification(specification)
+ local presets = specification.presets
+ if type(presets) == "string" then
+ presets = dofile(presets)
+ end
+ if type(presets) == "table" then
+ local m = getmetatable(presets)
+ if m then
+ setmetatable(m,defaults)
+ else
+ setmetatable(presets,defaults)
+ end
+ setmetatable(specification,{ __index = presets })
+ else
+ setmetatable(specification,defaults)
+ end
+ local templatefile = specification.templatefile or "query"
+ local queryfile = specification.queryfile or presets.queryfile or file.nameonly(templatefile) .. "-temp.sql"
+ local resultfile = specification.resultfile or presets.resultfile or file.nameonly(templatefile) .. "-temp.dat"
+ specification.queryfile = queryfile
+ specification.resultfile = resultfile
+ if trace_sql then
+ report_state("template file: %q",templatefile or "<none>")
+ report_state("query file: %q",queryfile)
+ report_state("result file: %q",resultfile)
+ end
+ return true
+end
+
+local function preparetemplate(specification)
+ local template = specification.template
+ if template then
+ local query = replacetemplate(template,specification.variables,'sql')
+ if not query then
+ report_state("error in template: %s",template)
+ elseif trace_queries then
+ report_state("query from template: %s",query)
+ end
+ return query
+ end
+ local templatefile = specification.templatefile
+ if templatefile then
+ local query = loadtemplate(templatefile,specification.variables,'sql')
+ if not query then
+ report_state("error in template file %q",templatefile)
+ elseif trace_queries then
+ report_state("query from template file %q: %s",templatefile,query)
+ end
+ return query
+ end
+ report_state("no query template or templatefile")
+end
+
+helpers.preparetemplate = preparetemplate
+
+-- -- -- we delay setting this -- -- --
+
+local currentmethod
+
+local function firstexecute(...)
+ local execute = methods[currentmethod].execute
+ sql.execute = execute
+ return execute(...)
+end
+
+function sql.setmethod(method)
+ currentmethod = method
+ sql.execute = firstexecute
+end
+
+sql.setmethod("client")
+
+-- helper:
+
+function sql.usedatabase(presets,datatable)
+ local name = datatable or presets.datatable
+ if name then
+ local method = presets.method and sql.methods[presets.method] or sql.methods.client
+ local base = presets.database or "test"
+ local basename = format("`%s`.`%s`",base,name)
+ local execute = nil
+ local m_execute = method.execute
+ if method.usesfiles then
+ local queryfile = presets.queryfile or format("%s-temp.sql",name)
+ local resultfile = presets.resultfile or format("%s-temp.dat",name)
+ execute = function(specification) -- variables template
+ if not specification.presets then specification.presets = presets end
+ if not specification.queryfile then specification.queryfile = queryfile end
+ if not specification.resultfile then specification.resultfile = queryfile end
+ return m_execute(specification)
+ end
+ else
+ execute = function(specification) -- variables template
+ if not specification.presets then specification.presets = presets end
+ return m_execute(specification)
+ end
+ end
+ local function unpackdata(records,name)
+ if records then
+ name = name or "data"
+ for i=1,#records do
+ local record = records[i]
+ local data = record[name]
+ if data then
+ record[name] = deserialize(data)
+ end
+ end
+ end
+ end
+ return {
+ presets = preset,
+ base = base,
+ name = name,
+ basename = basename,
+ execute = execute,
+ serialize = serialize,
+ deserialize = deserialize,
+ unpackdata = unpackdata,
+ }
+ end
+end
+
+
+-- local data = utilities.sql.prepare {
+-- templatefile = "test.sql",
+-- variables = { },
+-- host = "...",
+-- username = "...",
+-- password = "...",
+-- database = "...",
+-- }
+
+-- local presets = {
+-- host = "...",
+-- username = "...",
+-- password = "...",
+-- database = "...",
+-- }
+--
+-- local data = utilities.sql.prepare {
+-- templatefile = "test.sql",
+-- variables = { },
+-- presets = presets,
+-- }
+
+-- local data = utilities.sql.prepare {
+-- templatefile = "test.sql",
+-- variables = { },
+-- presets = dofile(...),
+-- }
+
+-- local data = utilities.sql.prepare {
+-- templatefile = "test.sql",
+-- variables = { },
+-- presets = "...",
+-- }
+
+-- for i=1,10 do
+-- local dummy = uuid() -- else same every time, don't ask
+-- end
+
+sql.tokens = {
+ length = 42, -- but in practice we will reserve some 50 characters
+ new = function()
+ return format("%s-%x06",osuuid(),random(0xFFFFF)) -- 36 + 1 + 6 = 42
+ end,
+}
+
+-- -- --
+
+-- local func, code = sql.makeconverter {
+-- { name = "a", type = "number" },
+-- { name = "b", type = "string" },
+-- { name = "c", type = "boolean" },
+-- { name = "d", type = { x = "1" } },
+-- { name = "e", type = os.fulltime },
+-- }
+--
+-- print(code)
+
+-- -- --
+
+if tex and tex.systemmodes then
+
+ local droptable = table.drop
+ local threshold = 16 * 1024 -- use slower but less memory hungry variant
+
+ function sql.prepare(specification,tag)
+ -- could go into tuc if needed
+ -- todo: serialize per column
+ local filename = format("%s-sql-result-%s.tuc",tex.jobname,tag or "last")
+ if tex.systemmodes["first"] then
+ local data, keys = sql.execute(specification)
+ if not data then
+ data = { }
+ end
+ if not keys then
+ keys = { }
+ end
+ io.savedata(filename,droptable({ data = data, keys = keys },#keys*#data>threshold))
+ return data, keys
+ else
+ local result = table.load(filename)
+ return result.data, result.keys
+ end
+ end
+
+else
+
+ sql.prepare = sql.execute
+
+end
+
+return sql
diff --git a/tex/context/base/util-sta.lua b/tex/context/base/util-sta.lua
new file mode 100644
index 000000000..f94c1acdf
--- /dev/null
+++ b/tex/context/base/util-sta.lua
@@ -0,0 +1,342 @@
+if not modules then modules = { } end modules ['util-sta'] = {
+ version = 1.001,
+ comment = "companion to util-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local format = string.format
+
+local trace_stacker = false trackers.register("stacker.resolve", function(v) trace_stacker = v end)
+
+local stacker = stacker or { }
+
+utilities.stacker = stacker
+
+local function start(s,t,first,last)
+ if s.mode == "switch" then
+ local n = tostring(t[last])
+ if trace_stacker then
+ s.report("start: %s",n)
+ end
+ return n
+ else
+ local r = { }
+ for i=first,last do
+ r[#r+1] = tostring(t[i])
+ end
+ local n = concat(r," ")
+ if trace_stacker then
+ s.report("start: %s",n)
+ end
+ return n
+ end
+end
+
+local function stop(s,t,first,last)
+ if s.mode == "switch" then
+ local n = tostring(false)
+ if trace_stacker then
+ s.report("stop: %s",n)
+ end
+ return n
+ else
+ local r = { }
+ for i=last,first,-1 do
+ r[#r+1] = tostring(false)
+ end
+ local n = concat(r," ")
+ if trace_stacker then
+ s.report("stop: %s",n)
+ end
+ return n
+ end
+end
+
+local function change(s,t1,first1,last1,t2,first2,last2)
+ if s.mode == "switch" then
+ local n = tostring(t2[last2])
+ if trace_stacker then
+ s.report("change: %s",n)
+ end
+ return n
+ else
+ local r = { }
+ for i=last1,first1,-1 do
+ r[#r+1] = tostring(false)
+ end
+ local n = concat(r," ")
+ for i=first2,last2 do
+ r[#r+1] = tostring(t2[i])
+ end
+ if trace_stacker then
+ s.report("change: %s",n)
+ end
+ return n
+ end
+end
+
+function stacker.new(name)
+
+ local s
+
+ local stack = { }
+ local list = { }
+ local ids = { }
+ local hash = { }
+
+ local hashing = true
+
+ local function push(...)
+ local t = { ... }
+ for i=1,#t do
+ insert(stack,t[i])
+ end
+ if hashing then
+ local c = concat(stack,"|")
+ local n = hash[c]
+ if not n then
+ n = #list+1
+ hash[c] = n
+ list[n] = fastcopy(stack)
+ end
+ insert(ids,n)
+ return n
+ else
+ local n = #list+1
+ list[n] = fastcopy(stack)
+ insert(ids,n)
+ return n
+ end
+ end
+
+ local function pop()
+ remove(stack)
+ remove(ids)
+ return ids[#ids] or s.unset or -1
+ end
+
+ local function clean()
+ if #stack == 0 then
+ if trace_stacker then
+ s.report("%s list entries, %s stack entries",#list,#stack)
+ end
+ end
+ end
+
+ local tops = { }
+ local top, switch
+
+ local function resolve_begin(mode)
+ if mode then
+ switch = mode == "switch"
+ else
+ switch = s.mode == "switch"
+ end
+ top = { switch = switch }
+ insert(tops,top)
+ end
+
+ local function resolve_step(ti) -- keep track of changes outside function !
+ -- todo: optimize for n=1 etc
+ local result = nil
+ local noftop = #top
+ if ti > 0 then
+ local current = list[ti]
+ if current then
+ local noflist = #current
+ local nofsame = 0
+ if noflist > noftop then
+ for i=1,noflist do
+ if current[i] == top[i] then
+ nofsame = i
+ else
+ break
+ end
+ end
+ else
+ for i=1,noflist do
+ if current[i] == top[i] then
+ nofsame = i
+ else
+ break
+ end
+ end
+ end
+ local plus = nofsame + 1
+ if plus <= noftop then
+ if plus <= noflist then
+ if switch then
+ result = s.change(s,top,plus,noftop,current,nofsame,noflist)
+ else
+ result = s.change(s,top,plus,noftop,current,plus,noflist)
+ end
+ else
+ if switch then
+ result = s.change(s,top,plus,noftop,current,nofsame,noflist)
+ else
+ result = s.stop(s,top,plus,noftop)
+ end
+ end
+ elseif plus <= noflist then
+ if switch then
+ result = s.start(s,current,nofsame,noflist)
+ else
+ result = s.start(s,current,plus,noflist)
+ end
+ end
+ top = current
+ else
+ if 1 <= noftop then
+ result = s.stop(s,top,1,noftop)
+ end
+ top = { }
+ end
+ return result
+ else
+ if 1 <= noftop then
+ result = s.stop(s,top,1,noftop)
+ end
+ top = { }
+ return result
+ end
+ end
+
+ local function resolve_end()
+ -- resolve_step(s.unset)
+ local noftop = #top
+ if noftop > 0 then
+ local result = s.stop(s,top,1,#top)
+ remove(tops)
+ top = tops[#tops]
+ switch = top and top.switch
+ return result
+ end
+ end
+
+ local function resolve(t)
+ resolve_begin()
+ for i=1,#t do
+ resolve_step(t[i])
+ end
+ resolve_end()
+ end
+
+ local report = logs.reporter("stacker",name or nil)
+
+ s = {
+ name = name or "unknown",
+ unset = -1,
+ report = report,
+ start = start,
+ stop = stop,
+ change = change,
+ push = push,
+ pop = pop,
+ clean = clean,
+ resolve = resolve,
+ resolve_begin = resolve_begin,
+ resolve_step = resolve_step,
+ resolve_end = resolve_end,
+ }
+
+ return s -- we can overload functions
+
+end
+
+-- local s = utilities.stacker.new("demo")
+--
+-- local unset = s.unset
+-- local push = s.push
+-- local pop = s.pop
+--
+-- local t = {
+-- unset,
+-- unset,
+-- push("a"), -- a
+-- push("b","c"), -- a b c
+-- pop(), -- a b
+-- push("d"), -- a b d
+-- pop(), -- a b
+-- unset,
+-- pop(), -- a
+-- pop(), -- b
+-- unset,
+-- unset,
+-- }
+--
+-- s.resolve(t)
+
+-- demostacker = utilities.stacker.new("demos")
+--
+-- local whatever = {
+-- one = "1 0 0 RG 1 0 0 rg",
+-- two = "1 1 0 RG 1 1 0 rg",
+-- [false] = "0 G 0 g",
+-- }
+--
+-- local concat = table.concat
+--
+-- local pdfliteral = nodes.pool.pdfliteral
+--
+-- function demostacker.start(s,t,first,last)
+-- local n = whatever[t[last]]
+-- -- s.report("start: %s",n)
+-- return pdfliteral(n)
+-- end
+--
+-- function demostacker.stop(s,t,first,last)
+-- local n = whatever[false]
+-- -- s.report("stop: %s",n)
+-- return pdfliteral(n)
+-- end
+--
+-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
+-- local n = whatever[t2[last2]]
+-- -- s.report("change: %s",n)
+-- return pdfliteral(n)
+-- end
+--
+-- demostacker.mode = "switch"
+--
+-- local whatever = {
+-- one = "/OC /test1 BDC",
+-- two = "/OC /test2 BDC",
+-- [false] = "EMC",
+-- }
+--
+-- demostacker = utilities.stacker.new("demos")
+--
+-- function demostacker.start(s,t,first,last)
+-- local r = { }
+-- for i=first,last do
+-- r[#r+1] = whatever[t[i]]
+-- end
+-- -- s.report("start: %s",concat(r," "))
+-- return pdfliteral(concat(r," "))
+-- end
+--
+-- function demostacker.stop(s,t,first,last)
+-- local r = { }
+-- for i=last,first,-1 do
+-- r[#r+1] = whatever[false]
+-- end
+-- -- s.report("stop: %s",concat(r," "))
+-- return pdfliteral(concat(r," "))
+-- end
+--
+-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
+-- local r = { }
+-- for i=last1,first1,-1 do
+-- r[#r+1] = whatever[false]
+-- end
+-- for i=first2,last2 do
+-- r[#r+1] = whatever[t2[i]]
+-- end
+-- -- s.report("change: %s",concat(r," "))
+-- return pdfliteral(concat(r," "))
+-- end
+--
+-- demostacker.mode = "stack"
diff --git a/tex/context/base/util-str.lua b/tex/context/base/util-str.lua
index 75cf443fb..377dd163f 100644
--- a/tex/context/base/util-str.lua
+++ b/tex/context/base/util-str.lua
@@ -62,11 +62,8 @@ function strings.newrepeater(str,offset)
return t
end
---~ local dashes = strings.newrepeater("--",-1)
-
---~ print(dashes[2])
---~ print(dashes[3])
---~ print(dashes[1])
+-- local dashes = strings.newrepeater("--",-1)
+-- print(dashes[2],dashes[3],dashes[1])
local extra, tab, start = 0, 0, 4, 0
diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua
index 28a6b8cc5..7a2da298e 100644
--- a/tex/context/base/util-tab.lua
+++ b/tex/context/base/util-tab.lua
@@ -10,10 +10,11 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch, rep = string.format, string.gmatch, string.rep
+local format, gmatch, rep, gsub = string.format, string.gmatch, string.rep, string.gsub
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
+local type, next, rawset, tonumber, loadstring = type, next, rawset, tonumber, loadstring
+local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -166,3 +167,118 @@ function tables.encapsulate(core,capsule,protect)
} )
end
end
+
+local function serialize(t,r,outer) -- no mixes
+ r[#r+1] = "{"
+ local n = #t
+ if n > 0 then
+ for i=1,n do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("%q,",v)
+ elseif tv == "number" then
+ r[#r+1] = format("%s,",v)
+ elseif tv == "table" then
+ serialize(v,r)
+ elseif tv == "boolean" then
+ r[#r+1] = format("%s,",tostring(v))
+ end
+ end
+ else
+ for k, v in next, t do
+ local tv = type(v)
+ if tv == "string" then
+ r[#r+1] = format("[%q]=%q,",k,v)
+ elseif tv == "number" then
+ r[#r+1] = format("[%q]=%s,",k,v)
+ elseif tv == "table" then
+ r[#r+1] = format("[%q]=",k)
+ serialize(v,r)
+ elseif tv == "boolean" then
+ r[#r+1] = format("[%q]=%s,",k,tostring(v))
+ end
+ end
+ end
+ if outer then
+ r[#r+1] = "}"
+ else
+ r[#r+1] = "},"
+ end
+ return r
+end
+
+function table.fastserialize(t,prefix)
+ return concat(serialize(t,{ prefix or "return" },true))
+end
+
+function table.deserialize(str)
+ if not str or str == "" then
+ return
+ end
+ local code = loadstring(str)
+ if not code then
+ return
+ end
+ code = code()
+ if not code then
+ return
+ end
+ return code
+end
+
+-- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
+
+function table.load(filename)
+ if filename then
+ local t = io.loaddata(filename)
+ if t and t ~= "" then
+ t = loadstring(t)
+ if type(t) == "function" then
+ t = t()
+ if type(t) == "table" then
+ return t
+ end
+ end
+ end
+ end
+end
+
+local function slowdrop(t)
+ local r = { }
+ local l = { }
+ for i=1,#t do
+ local ti = t[i]
+ local j = 0
+ for k, v in next, ti do
+ j = j + 1
+ l[j] = format("%s=%q",k,v)
+ end
+ r[i] = format(" {%s},\n",concat(l))
+ end
+ return format("return {\n%s}",concat(r))
+end
+
+local function fastdrop(t)
+ local r = { "return {\n" }
+ for i=1,#t do
+ local ti = t[i]
+ r[#r+1] = " {"
+ for k, v in next, ti do
+ r[#r+1] = format("%s=%q",k,v)
+ end
+ r[#r+1] = "},\n"
+ end
+ r[#r+1] = "}"
+ return concat(r)
+end
+
+function table.drop(t,slow)
+ if #t == 0 then
+ return "return { }"
+ elseif slow == true then
+ return slowdrop(t) -- less memory
+ else
+ return fastdrop(t) -- some 15% faster
+ end
+end
diff --git a/tex/context/base/util-tpl.lua b/tex/context/base/util-tpl.lua
new file mode 100644
index 000000000..4cde1863b
--- /dev/null
+++ b/tex/context/base/util-tpl.lua
@@ -0,0 +1,117 @@
+if not modules then modules = { } end modules ['util-tpl'] = {
+ 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"
+}
+
+-- This is experimental code. Coming from dos and windows, I've always used %whatever%
+-- as template variables so let's stick to it. After all, it's easy to parse and stands
+-- out well. A double %% is turned into a regular %.
+
+utilities.templates = utilities.templates or { }
+local templates = utilities.templates
+
+local trace_template = false trackers.register("templates.trace",function(v) trace_template = v end)
+local report_template = logs.reporter("template")
+
+local format = string.format
+local P, C, Cs, Carg, lpegmatch = lpeg.P, lpeg.C, lpeg.Cs, lpeg.Carg, lpeg.match
+
+-- todo: make installable template.new
+
+local replacer
+
+local function replacekey(k,t,recursive)
+ local v = t[k]
+ if not v then
+ if trace_template then
+ report_template("unknown key %q",k)
+ end
+ return ""
+ else
+ if trace_template then
+ report_template("setting key %q to value %q",k,v)
+ end
+ if recursive then
+ return lpegmatch(replacer,v,1,t)
+ else
+ return v
+ end
+ end
+end
+
+local sqlescape = lpeg.replacer {
+ { "'", "''" },
+ { "\\", "\\\\" },
+ { "\r\n", "\\n" },
+ { "\r", "\\n" },
+ -- { "\t", "\\t" },
+}
+
+local escapers = {
+ lua = function(s)
+ return format("%q",s)
+ end,
+ sql = function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+
+local function replacekeyunquoted(s,t,how,recurse) -- ".. \" "
+ local escaper = how and escapers[how] or escapers.lua
+ return escaper(replacekey(s,t,recurse))
+end
+
+local single = P("%") -- test %test% test : resolves test
+local double = P("%%") -- test 10%% test : %% becomes %
+local lquoted = P("%[") -- test %[test]" test : resolves test with escaped "'s
+local rquoted = P("]%") --
+
+local escape = double / '%%'
+local nosingle = single / ''
+local nodouble = double / ''
+local nolquoted = lquoted / ''
+local norquoted = rquoted / ''
+
+local key = nosingle * (C((1-nosingle)^1 * Carg(1) * Carg(2) * Carg(3))/replacekey) * nosingle
+local unquoted = nolquoted * ((C((1 - norquoted)^1) * Carg(1) * Carg(2) * Carg(3))/replacekeyunquoted) * norquoted
+local any = P(1)
+
+ replacer = Cs((unquoted + escape + key + any)^0)
+
+local function replace(str,mapping,how,recurse)
+ if mapping then
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+ return str
+ end
+end
+
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] }))
+-- print(replace("test '%[x]%' test",{ x = [[a 'x'  a]] },'sql'))
+
+templates.replace = replace
+
+function templates.load(filename,mapping,how,recurse)
+ local data = io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+ return replace(data,mapping,how,recurse)
+ else
+ return data
+ end
+end
+
+function templates.resolve(t,mapping,how,recurse)
+ if not mapping then
+ mapping = t
+ end
+ for k, v in next, t do
+ t[k] = replace(v,mapping,how,recurse)
+ end
+ return t
+end
+
+-- inspect(utilities.templates.replace("test %one% test", { one = "%two%", two = "two" }))
+-- inspect(utilities.templates.resolve({ one = "%two%", two = "two", three = "%three%" }))
diff --git a/tex/context/base/x-asciimath.mkiv b/tex/context/base/x-asciimath.mkiv
index 23caf13aa..ea6d5c3fa 100644
--- a/tex/context/base/x-asciimath.mkiv
+++ b/tex/context/base/x-asciimath.mkiv
@@ -68,7 +68,7 @@
\protect
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{x-asciimath.mkiv}
\enabletrackers[modules.asciimath.mapping]
diff --git a/tex/context/base/x-chemml.lua b/tex/context/base/x-chemml.lua
index 387935c8b..64bbb3408 100644
--- a/tex/context/base/x-chemml.lua
+++ b/tex/context/base/x-chemml.lua
@@ -28,7 +28,7 @@ function chemml.do_graphic(id)
for r, d, k in xml.elements(lxml.id(id),"cml:graphic") do
t[#t+1] = xml.tostring(d[k].dt)
end
- concat(concat(t,","))
+ context(concat(t,","))
end
function chemml.no_graphic(id)
diff --git a/tex/context/base/x-chemml.mkiv b/tex/context/base/x-chemml.mkiv
index 34aba3011..99a371107 100644
--- a/tex/context/base/x-chemml.mkiv
+++ b/tex/context/base/x-chemml.mkiv
@@ -11,34 +11,34 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+% This needs an update!
+
\writestatus{loading}{ConTeXt XML Macros / Chemistry}
\registerctxluafile{x-chemml}{}
\def\ctxmodulechemml#1{\directlua\zerocount{moduledata.chemml.#1}}
-\usemodule[pictex,chemic] % someday we will do structural fomulas in mp
-
%D The following code assumes a load||flush approach to \XML.
\unprotect
\startxmlsetups xml:cml:process
- \xmlstrip {\xmldocument} {cml:chem|cml:ichem|cml:dchem|cml:reaction|cml:molecule|cml:ion|cml:structure}
+ \xmlstrip {#1} {cml:chem|cml:ichem|cml:dchem|cml:reaction|cml:molecule|cml:ion|cml:structure}
- \xmlgrab {\xmldocument} {cml:*} {*}
- \xmlgrab {\xmldocument} {cml:gives|cml:equilibrium|cml:mesomeric} {cml:arrow}
- \xmlgrab {\xmldocument} {cml:plus|cml:minus|cml:equal} {cml:operator}
- \xmlgrab {\xmldocument} {cml:bond|cml:singlebond|cml:doublebound|cml:triplebond} {cml:bond}
+ \xmlgrab {#1} {cml:*} {cml:*}
+ \xmlgrab {#1} {cml:gives|cml:equilibrium|cml:mesomeric} {cml:arrow}
+ \xmlgrab {#1} {cml:plus|cml:minus|cml:equal} {cml:operator}
+ \xmlgrab {#1} {cml:bond|cml:singlebond|cml:doublebound|cml:triplebond} {cml:bond}
- \xmlgrab {\xmldocument} {pi::chemml} {cml:pi}
+ \xmlgrab {#1} {pi::chemml} {cml:pi}
\stopxmlsetups
\xmlregistersetup{xml:cml:process}
\xmlregisterns{cml}{chemml}
-\unexpanded\def\setupCMLappearance[#1]{\dodoubleargument\getparameters[@@CML#1]}
+\unexpanded\def\setupCMLappearance[#1]{\dodoubleargument\getparameters[@@CML#1]} % old stuff
\setupCMLappearance [ion] [\c!alternative=\v!a]
@@ -67,7 +67,7 @@
\xmlflush{#1}
\stopxmlsetups
-\def\doCMLtext#1#2#3% main top bot
+\unexpanded\def\doCMLtext#1#2#3% main top bot
{\setbox0\hbox{\doifsomething{#2}{\txx\setstrut\strut\ignorespaces#2\unskip}}%
\setbox2\hbox{\ignorespaces\strut#1\unskip}%
\setbox4\hbox{\doifsomething{#3}{\txx\setstrut\strut\ignorespaces#3\unskip}}%
@@ -163,7 +163,7 @@
\stopxmlsetups
\def\doCMLbond
- {\hrule\!!width\hsize\!!height.1ex\relax}
+ {\hrule\s!width\hsize\s!height.1ex\relax}
\def\dodoCMLbond#1#2#3%
{\begingroup
diff --git a/tex/context/base/x-dir-05.mkiv b/tex/context/base/x-dir-05.mkiv
index de1d3fa5f..379b3220a 100644
--- a/tex/context/base/x-dir-05.mkiv
+++ b/tex/context/base/x-dir-05.mkiv
@@ -52,13 +52,13 @@
\stopluacode
\def\getfilestatevariable#1#2%
- {\ctxlua{commands.getfilestatevariable("#1","#2")}}
+ {\ctxcommand{getfilestatevariable("#1","#2")}}
\def\savefilestate
{\dodoubleargument\dosavefilestate}
\def\dosavefilestate[#1][#2]%
- {\ctxlua{commands.savefilestate("#1","#2")}%
+ {\ctxcommand{savefilestate("#1","#2")}%
\setxvariables
[#1]
[name={#2},
diff --git a/tex/context/base/x-mathml.lua b/tex/context/base/x-mathml.lua
index 30e770190..cc7238f94 100644
--- a/tex/context/base/x-mathml.lua
+++ b/tex/context/base/x-mathml.lua
@@ -12,7 +12,7 @@ local type, next = type, next
local utf = unicode.utf8
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 utfchar = utf.char
local xmlsprint, xmlcprint, xmltext, xmlcontent = xml.sprint, xml.cprint, xml.text, xml.content
local getid = lxml.getid
local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
@@ -87,6 +87,8 @@ local o_replacements = { -- in main table
}
+local simpleoperatorremapper = utf.remapper(o_replacements)
+
--~ languages.data.labels.functions
local i_replacements = {
@@ -457,8 +459,7 @@ function xml.functions.remapopenmath(e)
end
function mathml.checked_operator(str)
- str = utfgsub(str,".",o_replacements)
- context(str)
+ context(simpleoperatorremapper(str))
end
function mathml.stripped(str)
@@ -481,10 +482,8 @@ end
function mathml.mo(id)
local str = xmlcontent(getid(id)) or ""
- local rep = gsub(str,"&.-;","")
- local rep = utfgsub(rep,".",o_replacements)
- context(rep)
- -- context.mo(rep) -- fails with \left etc
+ local rep = gsub(str,"&.-;","") -- todo
+ context(simpleoperatorremapper(rep))
end
function mathml.mi(id)
@@ -524,10 +523,7 @@ function mathml.mfenced(id) -- multiple separators
elseif n == 1 then
xmlsprint(collected[1]) -- to be checked
else
- local t = { }
- for s in utfgmatch(separators,"[^%s]") do
- t[#t+1] = s
- end
+ local t = utf.split(separators,true)
for i=1,n do
xmlsprint(collected[i]) -- to be checked
if i < n then
@@ -646,8 +642,8 @@ 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
+ str = gsub(str,"&.-;","")
+ for s in utfcharacters(str) do
m[#m+1] = { tag, s }
end
if tag == "mn" then
@@ -658,7 +654,7 @@ str = gsub(str,"&.-;","")
end
elseif tag == "mspace" or tag == "mline" then
local str = e.at.spacing or ""
- for s in utfcharacters(str) do -- utf.gmatch(str,".") btw, the gmatch was bugged
+ for s in utfcharacters(str) do
m[#m+1] = { tag, s }
end
-- elseif tag == "mline" then
diff --git a/tex/context/base/x-mathml.mkiv b/tex/context/base/x-mathml.mkiv
deleted file mode 100644
index f64fdbc74..000000000
--- a/tex/context/base/x-mathml.mkiv
+++ /dev/null
@@ -1,2366 +0,0 @@
-%D \module
-%D [ file=x-mathml,
-%D version=2008.05.29,
-%D title=\CONTEXT\ XML Modules,
-%D subtitle=Loading \MATHML\ Filters,
-%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.
-
-% \xmlfilter{#1}{/*/name()} -> \xmltag
-
-% 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}{}
-
-\def\ctxmodulemathml#1{\directlua\zerocount{moduledata.mathml.#1}}
-
-\startxmlsetups xml:mml:define
- \xmlsetsetup{\xmldocument} {(formula|subformula)} {mml:formula}
- \xmlfilter {\xmldocument} {omt:*/function(remapopenmath)}
- \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:csymbol)}
-\stopxmlsetups
-
-\xmlregisterns{omt}{openmath}
-\xmlregisterns{mml}{mathml}
-
-\xmlregistersetup{xml:mml:define}
-
-\def\MMLhack{\let\MMLpar\par \let\par\relax \everyvbox{\let\par\MMLpar}}
-
-\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
- \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
- \inlinemathematics{\MMLhack\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:dmath
- \displaymathematics{\MMLhack\xmlflush{#1}}
-\stopxmlsetups
-
-%D First we define some general formula elements.
-
-\startxmlsetups mml:formula
- \edef\mmlformulalabel {\xmlatt{#1}{label}\xmlatt{#1}{id}}
- \edef\mmlformulasublabel{\xmlatt{#1}{sublabel}\xmlatt{#1}{id}}
- \doifsomething\mmlformulalabel{\placeformula[\mmlformulalabel]{\mmlformulasublabel}}
- \startformula\MMLhack\xmlfirst{#1}{/mml:math}\stopformula
-\stopxmlsetups
-
-\setfalse\mmlignoredelimiter
-\settrue \mmlsomeleftdelimiter
-
-\def\MMLleftorright
- {\ifconditional\mmlsomeleftdelimiter
- \setfalse\mmlsomeleftdelimiter\expandafter\MMLleft
- \else
- \settrue \mmlsomeleftdelimiter\expandafter\MMLright
- \fi}
-
-\ifx\MMLleft \undefined \let\MMLleft \firstofoneargument \fi
-\ifx\MMLright \undefined \let\MMLright \firstofoneargument \fi
-\ifx\MMLmiddle\undefined \let\MMLmiddle\firstofoneargument \fi
-
-\def\mmlleftdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLleft #1}\fi}
-\def\mmlrightdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLright #1}\fi}
-\def\mmlmiddledelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLmiddle #1}\fi}
-\def\mmlleftorrightdelimiter#1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{\MMLleftorright#1}\fi}
-
-\def\mmlchar#1{\char#1 } % used in lua code
-
-% \newcount\delimiternesting \appendtoks \delimiternesting\zerocount \to \everymathematics
-
-% \def\mmlleftdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{%
-% \advance\delimiternesting\plusone \MMLleft #1}\fi}
-% \def\mmlrightdelimiter #1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{%
-% \advance\delimiternesting\plusone \MMLright#1}\fi}
-% \def\mmlmiddledelimiter#1{\ifconditional\mmlignoredelimiter#1\else\normalordelimiter{#1}{%
-% \ifcase\delimiternesting\MMLleft\else\MMLmiddle\fi#1}\fi}
-
-
-%D Remark: from now on this is a module and no longer an xtag
-%D filter. There is an intermediate cleaner module but it has
-%D some namespace limitations. Here we do it the \MKIV\ way.
-
-\def\widevec#1%
- {\vbox{\mathsurround\zeropoint\ialign{##\crcr
- \rightarrowfill\crcr\noalign{\nointerlineskip}%
- \startimath\hfil\displaystyle{#1}\hfil\stopimath\crcr}}}
-
-%D The rendering macros:
-
-\def\MMLrm{\mr}
-
-\def\MMLseparator#1{\removeunwantedspaces{#1}\ignorespaces} % nils space after separator
-\def\MMLseparator#1{,} % todo, for europe we need to block the space
-
-%D Since I only had the draft of MathML 2 and later 3 as example of
-%D rendering, there are probably a lot of omissions and
-%D misinterpretations. At least I learned some bits and
-%D pieces of math rendering.
-%D
-%D The main complications were not so much the math, but to
-%D find the most efficient way to handle elements without
-%D spacing beging messed up. The first implementation was
-%D aimed at getting reasonable output, this second
-%D implementation is already better in terms of handling
-%D nesting, and I will definitely need a third one that has
-%D more efficient and less ugly code.
-%D
-%D The \TEX\ part is not that complicated and once the
-%D preprocessor was okay, the rest way just a lot of keying
-%D and testing. It all comes down to gobbling, redefining,
-%D and not so much to parsing.
-%D
-%D The second implementation expanded the whole math sequence
-%D into an internal \TEX\ representation. This is a rather clean
-%D and fast process. Filtering and testing takes place by
-%D redefining teh internal representation macros.
-%D
-%D The third implementation may look a bit more messy in some
-%D respects. This is because in \TEX\ it's not that trivial to
-%D implement a tree handler. We use a stack for the \type {apply}
-%D element and other sequential content. Occasionally we need to
-%D peek into child elements which involves messy code. This
-%D implementation is closer to the normal \XML\ handling in
-%D \CONTEXT.
-
-%D We start with the parent elements and the option handler.
-
-\def\xmlmathmldirective#1{\dosetvalue{MML#1}}
-
-%def\xmlmathmldirective#1#2#3{[#1][#2][#3]\dosetvalue{MML#1}{#2}{#3}}
-
-%D In the styles, options can be set with:
-
-\unexpanded\def\setupMMLappearance[#1]{\dodoubleargument\getparameters[MML#1]} % no @@ because passed to lua
-
-%D We will apply inner math to all bits and pieces made up by an
-%D \type {apply}.
-
-\def\MMLmathinner
- {\ifinner
- \expandafter\firstofoneargument
- \else
- \expandafter\mathinner
- \fi}
-
-%D Auxiliary MathML macros: (to be generalized)
-
-\def\mmlfirst #1{\xmlelement{#1}{1}} % we can move these inline if needed
-\def\mmlsecond #1{\xmlelement{#1}{2}}
-\def\mmlthird #1{\xmlelement{#1}{3}}
-\def\mmlprelast#1{\xmlelement{#1}{-2}}
-\def\mmllast #1{\xmlelement{#1}{-1}}
-
-\starttexdefinition doifelsemmlfunction #1
- \xmldoifelse {#1} {/mml:fn} {
- \firstoftwoarguments
- } {
- \xmldoifelse {#1} {/mml:apply/mml:fn} {
- \firstoftwoarguments
- } {
- \xmldoifelse {#1} {/mml:ci[@type=='fn']} {
- \firstoftwoarguments
- } {
- \secondoftwoarguments
- }
- }
- }
-\stoptexdefinition
-
-%D Special features:
-
- \newtoks \@@postponedMMLactions \setfalse \somepostponedMMLactions
-
- \def\postponeMMLactions#1%
- {\global\settrue\somepostponedMMLactions
- \global\@@postponedMMLactions\expandafter{\the\@@postponedMMLactions#1}}
-
- \def\postponedMMLactions
- {\global\setfalse\somepostponedMMLactions
- \@EA\global\@EA\@@postponedMMLactions\@EA\emptytoks
- \the\@@postponedMMLactions}
-
-%D A couple of lists:
-
-\convertargument
- mml:times|mml:divide|mml:power|%
- mml:lt|mml:gt|mml:eq|mml:leq|mml:geq|%
- mml:in|mml:inverse|%
- mml:fn|%
- mml:floor|mml:ceiling|%
- mml:mean|%
- mml:selector|%
- mml:abs|mml:int|mml:limit|mml:sum|mml:product|%
- mml:outerproduct|mml:innerproduct|mml:scalarproduct%
-\to \MMLcmainresetlist
-
-\convertargument
- mml:sin|mml:arcsin|mml:sinh|mml:arcsinh|%
- mml:cos|mml:arccos|mml:cosh|mml:arccosh|%
- mml:tan|mml:arctan|mml:tanh|mml:arctanh|%
- mml:cot|mml:arccot|mml:coth|mml:arccoth|%
- mml:csc|mml:arccsc|mml:csch|mml:arccsch|%
- mml:sec|mml:arcsec|mml:sech|mml:arcsech|%
- mml:ln|mml:exp|mml:log|%
- mml:abs|mml:int|mml:limit|mml:sum|mml:product|%
- mml:fn%
-\to \MMLcfunctionlist
-
-\convertargument
- mml:sin|mml:arcsin|mml:sinh|mml:arcsinh|%
- mml:cos|mml:arccos|mml:cosh|mml:arccosh|%
- mml:tan|mml:arctan|mml:tanh|mml:arctanh|%
- mml:cot|mml:arccot|mml:coth|mml:arccoth|%
- mml:csc|mml:arccsc|mml:csch|mml:arccsch|%
- mml:sec|mml:arcsec|mml:sech|mml:arcsech|%
- mml:ln|mml:exp|mml:log|%
- mml:abs%
-\to \MMLcpurefunctionlist
-
-\convertargument
- mml:diff|mml:partialdiff|mml:root%
-\to \MMLcconstructlist
-
-%D We use inner and grouping (begin/end and no b/e) else we
-%D get problems with 1/2(1+2) and alike (todo: ask taco).
-%D
-%D The problem with apply is that we need to take care of
-%D several situations, like:
-%D
-%D \starttyping
-%D <apply> <.../> ...
-%D <apply> <fn> ...
-%D <apply> <apply> <ci> ...
-%D <apply> <apply> <fn> <ci> ...
-%D \stoptyping
-%D
-%D Because we translated version 2 of this renderer into
-%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}
-
-\let\MMLctempresetlist\empty \def\setMMLcreset{\edef\MMLctempresetlist}
-
-\let\MMLdoL\donothing
-\let\MMLdoR\donothing
-
-\newcount\mmlapplydepth \def\MMLcreset{\mmlapplydepth\zerocount}
-
-\startxmlsetups mml:apply
- \MMLmathinner {
- \xmldoif {#1} {/(\MMLcmainresetlist\string|\MMLctempresetlist)} {
- % \MMLcreset
- }
- \edef\mmlapplyopentoken {\xmlatt{#1}{open}}
- \edef\mmlapplyclosetoken{\xmlatt{#1}{close}}
- \ifcase\mmlapplydepth \else
- \ifx\mmlapplyopentoken\empty
- \def\mmlapplyopentoken {(}
- \def\mmlapplyclosetoken{)}
- \fi
- \fi
- \advance\mmlapplydepth\plusone
- \begingroup
- \ifx\mmlapplyopentoken\empty
- \let\MMLdoL\donothing
- \let\MMLdoR\donothing
- \else
- \edef\MMLdoL{\noexpand\left \mmlapplyopentoken }
- \edef\MMLdoR{\noexpand\right\mmlapplyclosetoken}
- \fi
- \let\MMLctempresetlist\empty
- \xmldoifelse {#1} {/mml:apply} {
-% % <apply> <apply> ... </apply> <ci> .. </ci> </apply>
-% \xmldoifelse {#1} {/mml:apply(mml:plus|mml:minus)} {% [a]
-% % yet incomplete and rather untested
-% % <apply> <apply> <minus/> <tan/> <cos/> </apply> <ci>x</ci> </apply>
- } {% [b]
-% \MMLcreset
- }
-% \MMLdoL
-% \mmlfirst{#1}
-% \ifconditional\somepostponedMMLactions
-% \postponedMMLactions
-% \else
-% \left(\MMLcreset\mmlsecond{#1}\right)
-% \fi
-% \MMLdoR
-% } {
- \edef\mmlapplyaction{\xmlfilter{#1}{/*/name()}}
- \doifsetupselse {mml:apply:mml:\mmlapplyaction} {
- \xmlsetup{#1}{mml:apply:mml:\mmlapplyaction}
- } {
-% \MMLdoL
- \xmlsetup{#1}{mml:\xmlfilter{#1}{/*/name()}}
-% \MMLdoR
- }
-% }
- \endgroup
- \advance\mmlapplydepth\minusone
- }
-\stopxmlsetups
-
-\startxmlsetups mml:apply:mml:apply
- \xmlflush{#1}
- \xmlall{#1}{../[position()>1]}
-\stopxmlsetups
-
-\startxmlsetups mml:apply:mml:fn
- \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
- \negthinspace % not enough
- \left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right)
- \fi
- \MMLdoR
- }
- } {
- \MMLcreset
- \MMLdoL
- \xmlall{#1}{/*}
- \MMLdoR
- }
-\stopxmlsetups
-
-\startxmlsetups mml:apply:mml:csymbol
- \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
- \left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right)
- \fi
-\stopxmlsetups
-
-% reln
-
-\startxmlsetups mml:reln
- \writestatus{XML}{MathML element "reln" is obsolete}
-\stopxmlsetups
-
-% fn
-
-% plusminus ±
-
-\startxmlsetups mmc:fn:\utfchar{"00B1}
- \MMLdoL
- \xmlconcat{#1}{/[position()>1]}{\utfchar{"00B1}}
- \MMLdoR
-\stopxmlsetups
-
-% minusplus
-
-\startxmlsetups mmc:fn:\utfchar{"2213}
- \MMLdoL
- \xmlconcat{#1}{/[position()>1]}{\utfchar{"2213}}
- \MMLdoR
-\stopxmlsetups
-
-\startxmlsetups mmc:fn
- \begingroup
- \edef\mmlnoffn{\xmlcount{#1}{/*}}
- \ifnum\mmlnoffn>\plustwo
- \def\MMCfnleft {\left(}
- \def\MMCfnright{\right)}
- \else
- \let\MMCfnleft \relax
- \let\MMCfnright\relax
- \fi
- \xmldoifelse {#1} {/mml:ci} { % first
- \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}
- }
- } {
- \xmldoifelse {#1} {/mml:apply} { % first
- \xmldoifelse {#1} {/(mml:plus\string|mml:minus)} {
- \left(\mmlfirst{#1}\right)
- } {
- \mmlfirst{#1}
- }
- \ifnum\mmlnoffn>\plusone
- \left(\xmlall{#1}{/!mml:apply}\right)
- \fi
- } {
- \MMLcreset
- \negthinspace
- \MMCfnleft
- \ifnum\mmlnoffn=\plustwo,\fi
- \xmlconcat{#1}{/*}{2}{}{\MMLseparator,}
- \MMCfnright
- }
- }
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mmc:fn:apply % where used?
- \xmldoifelse {#1} {/mml:ci} { % first
- \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
- \negthinspace
- \left(\MMLcreset\xmlconcat{#1}{2}{}{\MMLseparator,}\right)
- \fi
- }
- } {
- \endgroup
- \MMLcreset
- \mmlfirst{#1}
- }
-\stopxmlsetups
-
-%D The next definition provide a kind of plug-in mechanism (see
-%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}
- \text{#4}
- } {
- \doifsetupselse {mml:csymbol:#1} {
- % full url
- \directsetup{mml:csymbol:#1}
- } {
- % somename (fallback)
- \doifsetupselse {mml:csymbol:#2} {
- \directsetup{mml:csymbol:#2}
- } {
- \xmlval{mmc:cs}{#3}{}% todo
- }
- }
- }
-\stoptexdefinition
-
-\startxmlsetups mml:csymbol
- \ctxmodulemathml{csymbol("#1")}
-\stopxmlsetups
-
-\startxmlsetups mml:csymbol:cdots
- \cdots
-\stopxmlsetups
-
-% \startxmlsetups mml:csymbol:<url> \stopxmlsetups
-
-%D Alternative b will convert periods into comma's:
-
-\setupMMLappearance[cn] [\c!alternative=\v!a]
-\setupMMLappearance[polar] [\c!alternative=\v!a] % a|b|c
-\setupMMLappearance[float] [\c!symbol=\v!no] % \v!yes|dot
-\setupMMLappearance[enotation][\c!symbol=\v!no] % \v!yes|dot
-\setupMMLappearance[base] [\c!symbol=\v!numbers] % digits|characters|text|no
-
-\startxmlsetups mml:cs \xmlcommand{#1}{/}{mml:cs:\xmlattdef{#1}{type}{default}} \stopxmlsetups
-\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 / todo: \mn{...}
-
-\startxmlsetups mml:cn:default
- \mathopnolimits{\xmlflush{#1}}
-\stopxmlsetups
-
-% helpers ci
-
-\startxmlsetups mml:ci:default
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:set
- {\blackboard{\xmlflush{#1}}} % todo
-\stopxmlsetups
-
-\startxmlsetups mml:ci:vector
- \widevec{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:matrix
- {\bi\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:function
- \xmlflush{#1}% \negthinspace
-\stopxmlsetups
-
-\startxmlsetups mml:ci:fn
- \xmlsetup{#1}{mml:ci:function}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:complex-cartesian
- \xmlsetup{#1}{mml:cn:complex}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:complex
- \xmlsetup{#1}{mml:cn:complex}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:complex-polar
- \xmlsetup{#1}{mml:cn:polar}
-\stopxmlsetups
-
-\startxmlsetups mml:ci:polar
- \xmlsetup{#1}{mml:cn:polar}
-\stopxmlsetups
-
-% helpers ci
-
-\startxmlsetups mml:cn:default
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:integer
- \edef\mmlintegerbase{\xmlattdef{#1}{base}{}}
- \ifx\mmlintegerbase\empty
- \xmlflush{#1}
- \else
- \doifelse \MMLbasesymbol \v!no {
- \MMLcCNbasedata{\xmlflush{#1}}
- } {
- \MMLcCNbasedata{\xmlflush{#1}}\normalsubscript{
- \hbox {\startimath
- \mr
- \scriptscriptstyle
- \processaction
- [\MMLbasesymbol]
- [\v!characters=>\MMLcCNbasestring BODH,
- \v!text=>\MMLcCNbasestring{BIN}{OCT}{DEC}{HEX},
- \s!unknown=>\mmlintegerbase]
- \stopimath}
- }
- }
- \fi
-\stopxmlsetups
-
-\def\MMLcCNbasedata#1%
- {\ifnum\mmlintegerbase>10 \relax{\mr#1}\else#1\fi}
-
-\def\MMLcCNbasestring#1#2#3#4%
- {\ifnum\mmlintegerbase= 2 #1\else
- \ifnum\mmlintegerbase= 8 #2\else
- \ifnum\mmlintegerbase=10 #3\else
- \ifnum\mmlintegerbase=16 #4\else
- \mmlintegerbase \fi\fi\fi\fi}
-
-\startxmlsetups mml:cn:polar
- \xmlsetup{#1}{mml:cn:polar:\MMLpolaralternative}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:polar:a
- \ctxmodulemathml{cpolar_a("#1")}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:polar:b
- {\mr e}\normalsuperscript{\xmlsnippet{#1}{1}+\xmlsnippet{#1}{3}\thinspace{\mr i}}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:polar:c
- \exp\left(\xmlsnippet{#1}{1}+\xmlsnippet{#1}{3}\thinspace{\mr i}\right)
-\stopxmlsetups
-
-\startxmlsetups mml:cn:complex-polar
- \xmlsetup{#1}{mml:cn:polar}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:complex % todo ( )
- \left(\xmlsnippet{#1}{1} + \xmlsnippet{#1}{3}\thinspace{\mr i}\right)
-\stopxmlsetups
-
-\startxmlsetups mml:cn:complex-cartesian
- \xmlsetup{#1}{mml:cn:complex}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:float
- \doifelse \MMLfloatsymbol \v!no {
- % make sure that e shows up ok
- \mathopnolimits{\xmlflush{#1}}
- } {
- % we should ignore \entities !
- \edef\mmlfloatstring{\xmlflush{#1}}
- \splitstring\mmlfloatstring\at e\to\first\and\last
- \ifx\first\empty
- \mmlfloatstring
- \else\ifx\last\empty
- \mmlfloatstring
- \else
- \first
- \doifelse \MMLfloatsymbol {dot} \cdot \times
- 10\normalsuperscript{\last}
- \fi \fi
- }
-\stopxmlsetups
-
-\startxmlsetups mml:cn:real
- \xmlsetup{#1}{mml:cn:float}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:e-notation
- \doifelse \MMLenotationsymbol \v!no {
- \xmlsnippet{#1}{1}
- \unskip\mathopnolimits{e}\ignorespaces
- \xmlsnippet{#1}{3}
- } {
- \xmlsnippet{#1}{1}
- \doifelse \MMLenotationsymbol {dot} \cdot
- \times10\normalsuperscript{\xmlsnippet{#1}{3}}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:cn:logical
- \mathopnolimits{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:cn:rational
- \xmldoifelse {#1} {/mml:sep} {
- \frac
- {\xmlsnippet{#1}{1}}
- {\xmlsnippet{#1}{3}}
- } {
- \xmlflush{#1}
- }
-\stopxmlsetups
-
-% interval
-
-\setupMMLappearance[interval][\c!alternative=\v!a,\c!separator={,}]
-
-% when empty element, then it's an apply
-
-\startxmlsetups mml:interval
- \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
-
-\startxmlsetups mml:interval:closed
- \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
-\stopxmlsetups
-
-\startxmlsetups mml:interval:open-closed
- \doifelse \MMLintervalalternative \v!b {
- \left<\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
- } {
- \left(\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right]
- }
-\stopxmlsetups
-
-\startxmlsetups mml:interval:closed-open
- \doifelse \MMLintervalalternative \v!b {
- \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right>
- } {
- \left[\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right)
- }
-\stopxmlsetups
-
-\startxmlsetups mml:interval:open
- \doifelse \MMLintervalalternative \v!b {
- \left<\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right>
- } {
- \left(\mmlintervalfirst{#1}\MMLseparator\MMLintervalseparator\mmlintervalsecond{#1}\right)
- }
-\stopxmlsetups
-
-% inverse
-
-\setfalse\xmlinversefunction
-
-\startxmlsetups mml:apply:inverse
- \settrue\xmlinversefunction
- \xmlsetup{#1}{mml:\xmlfilter{#1}{/mml:apply/*[2]/name()}}
-\stopxmlsetups
-
-% condition
-
-% maybe a fast \xmlnonfirst
-
-% instead of the following we could do \xmlcontent{#1}{/mml:bvar} etc
-
-\startxmlsetups mml:bvar \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:lowlimit \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:uplimit \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:degree \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:logbase \xmlflush{#1} \stopxmlsetups
-\startxmlsetups mml:fn \xmlflush{#1} \stopxmlsetups
-
-\startxmlsetups mml:condition
-% \xmldoif {#1} {/mml:bvar} {
-% \xmlfirst{#1}{/mml:bvar}\mid
-% }
- \xmlall{#1}{/!(mml:condition\string|mml:bvar)}
-\stopxmlsetups
-
-% declare
-
-\setupMMLappearance[declare][\c!state=\v!start]
-
-\startxmlsetups mml:declare
- \doif \MMLdeclarestate \v!start {
- \mathopnolimits{declare}
- \mmlfirst{#1}
- \ifnum\xmlcount{#1}{/*}>\plusone
- \thickspace
- \mathopnolimits{as}
- \thickspace
- \fi
- \mmlsecond{#1}
- }
-\stopxmlsetups
-
-% lambda
-
-\setupMMLappearance[lambda][\c!alternative=b]
-
-\startxmlsetups mml:lambda
- \begingroup
- \doifelse \MMLlambdaalternative \v!a {
- \lambda\left(\xmlconcat{#1}{/!mml:lambda}{\MMLseparator,}\right)
- } {
- \ifnum\xmlcount{#1}{/mml:bvar}>\plusone
- \left(\xmlconcat{#1}{/mml:bvar}{\MMLseparator,}\right)
- \else
- \xmlfirst{#1}{/mml:bvar}
- \fi
- \mapsto
- \MMLcreset
- \xmlall{#1}{/!(mml:bvar|mml:lambda)}
- }
- \endgroup
-\stopxmlsetups
-
-% compose
-
-\startxmlsetups mml:compose
- \begingroup
- \MMLcreset
-% \let\MMLcCIfunction\firstofoneargument % brrr ? ? ?
- \doifelsemmlfunction {#1} {
- \left(\xmlconcat{#1}{/!mml:compose}{\circ}\right)
- } {
- \xmlconcat{#1}{/!mml:compose}{\circ}
- }
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:image
- \mathopnolimits{image} \left( {\mr\xmlfilter{#1}{/!mml:image/tag()}} \right)
-\stopxmlsetups
-
-\setupMMLappearance[piece][\c!separator=]
-
-\startxmlsetups mml:piecewise
- \processaction
- [\MMLpieceseparator]
- [ \v!yes=>\def\theMMLpieceseparator{,&},
- \v!no=>\def\theMMLpieceseparator{&},
- \s!default=>\def\theMMLpieceseparator{&},
- \s!unknown=>\def\theMMLpieceseparator{\,\,\hbox{\MMLpieceseparator}\,\,}]
- \cases{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:piece
- \mmlfirst{#1}\theMMLpieceseparator\mathematics{\mmlsecond{#1}}\crcr
-\stopxmlsetups
-
-\startxmlsetups mml:otherwise
-% \xmlflush{#1}\MMLcPIECEseparator&{\mr otherwise}\crcr
- \xmlflush{#1}&{\mr otherwise}\crcr
-\stopxmlsetups
-
-% end of piece
-
-\startxmlsetups mml:quotient
- \lfloor\mmlsecond{#1}/\mmlthird{#1}\rfloor
-\stopxmlsetups
-
-\startxmlsetups mml:factorial
- \xmlall{#1}{/!factorial}!
-\stopxmlsetups
-
-\setupMMLappearance [divide] [\c!level=\!!maxcard,\c!alternative=\v!a]
-
-\newcount\mmldividelevel
-
-\startxmlsetups mml:divide
- \advance\mmldividelevel\plusone
- \doifelse \MMLdividealternative \v!b {
- \mmlsecond{#1}/\mmlthird{#1}
- } {
- \ifnum \mmldividelevel > \MMLdividelevel \relax % threshold
- \mmlsecond{#1}/\mmlthird{#1}
- \else
- \MMLcreset
- \frac{\MMLcreset\mmlsecond{#1}}{\MMLcreset\mmlthird{#1}}
- \fi
- }
- \advance\mmldividelevel\minusone
-\stopxmlsetups
-
-% min max
-
-\startxmlsetups mml:min \mathopnolimits{min} \xmlsetup{#1}{mml:minmax} \stopxmlsetups
-\startxmlsetups mml:max \mathopnolimits{max} \xmlsetup{#1}{mml:minmax} \stopxmlsetups
-
-\startxmlsetups mml:minmax
- \xmldoif {#1} {/mml:bvar} {
- {}\normalsubscript{\xmlfirst{#1}{/mml:bvar}}
- }
- \left\{
- \xmlconcat{#1}{/!(mml:bvar\string|mml:max\string|mml:min)}{\MMLseparator,}
- \right\}
-\stopxmlsetups
-
-% minus plus
-
-\setupMMLappearance [plus] [\c!alternative=\v!a] % b = no sign -> 3 1/4
-\setupMMLappearance [sign] [\c!reduction=\v!yes]
-
-% alternative b -> geen sign
-
-% branch needed, else (a-b) + (c-d) goes wrong
-% reset check in case of (-x) + 37
-% reset check in case of (-x) + 37
-
-\newcount\mmlpluscounter
-
-\startxmlsetups mml:plus
- \doifelse \MMLsignreduction \v!yes {
- \MMLdoL
- \xmlsetup{#1}{mml:plus:reset}
- \xmlcommand{#1}{/!mml:plus}{mml:plus:body}
- \MMLdoR
- } {
- \ifnum\xmlcount{#1}{/!mml:plus}=\plusone
- +\xmlfirst{#1}{/!mml:plus}
- \else
- \MMLdoL
- \xmlconcat{#1}{/!mml:plus}{+}
- \MMLdoR
- \fi
- }
-\stopxmlsetups
-
-\startxmlsetups mml:plus:reset
- \mmlpluscounter\zerocount
-\stopxmlsetups
-
-\startxmlsetups mml:plus:body
- \advance\mmlpluscounter\plusone
- \ifnum\mmlpluscounter>\plusone
- \xmldoifelse{#1}{/mml:minus} {
- \ifnum\xmlcount{#1}{/!mml:minus}>\plusone
- +
- \fi
- } {
- \doifelse {\xmlatt{#1}{type}} {rational} {
- % fraction
- } {
- +
- }
- }
- \fi
- \xmldirect{#1}
-\stopxmlsetups
-
-\newcount\mmlminuscounter
-
-\startsetups mml:minus
- \doifelse \MMLsignreduction \v!yes {
- \ifnum\xmlcount{#1}{/!mml:minus}=\plusone
- -\xmlfirst{#1}{/!mml:minus}
- \else
- \MMLdoL
- \xmlsetup{#1}{mml:minus:reset}
- \xmlcommand{#1}{/!mml:minus}{mml:minus:body}
- \MMLdoR
- \fi
- } {
- \left( % \MMLdoL
- \ifnum\xmlcount{#1}{/!mml:minus}=\plusone
- -\xmlfirst{#1}{/!mml:minus}
- \else
- \xmlsetup{#1}{mml:minus:reset}
- \xmlcommand{#1}{/!mml:minus}{mml:minus:body}
- \fi
- \right) % \MMLdoR
- }
-\stopsetups
-
-\startxmlsetups mml:minus:reset
- \mmlminuscounter\zerocount
-\stopxmlsetups
-
-\startxmlsetups mml:minus:body
- % we can slso use concat here
- \advance\mmlminuscounter\plusone
- \ifnum\mmlminuscounter>\plusone
- -
- \fi
- \xmldirect{#1}
-\stopxmlsetups
-
-% power
-
-\setupMMLappearance[power][\c!reduction=\v!yes]
-
-\let\MMLpowerelement\empty
-
-\startxmlsetups mml:power
- \xmldoifelse {#1} {/mml:apply} {
- \doifelse \MMLpowerreduction \v!yes {
- \xmldoifelse {#1} {/mml:apply/(\MMLcfunctionlist)} {
- \gdef\MMLpowerelement{\mmlthird{#1}}% postpone, no xdef
- \MMLcreset\mmlsecond{#1}
- } {
- \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript{\MMLcreset\mmlthird{#1}}
- }
- } {
- \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript{\MMLcreset\mmlthird{#1}}
- }
- } {
- \mmlsecond{#1}\normalsuperscript{\MMLcreset\mmlthird{#1}}
- }
-\stopxmlsetups
-
-% rem
-
-\startxmlsetups mml:rem
- \xmlconcat{#1}{/!mml:rem}{\mathopnolimits{mod}}
-\stopxmlsetups
-
-\setupMMLappearance [times] [\c!symbol=\v!no,\c!auto=\v!yes] % new, auto catches cn cn cn
-
-\startxmlsetups mml:times
- \setMMLcreset{\MMLcfunctionlist\string|\MMLcconstructlist}%
- \doifelse\MMLtimesauto\v!no {
- \let\MMLtimes@@symbol\MMLtimessymbol
- } {
- \xmldoifelse {#1} {/mml:cn[name(1) == 'mml:cn']} {% name(1) is next one
- \doifinsetelse\MMLtimessymbol{\v!yes,\v!no} {
- \let\MMLtimes@@symbol\v!yes
- } {
- \let\MMLtimes@@symbol\MMLtimessymbol
- }
- } {
- \let\MMLtimes@@symbol\MMLtimessymbol
- }
- }
- \doifelse\MMLtimes@@symbol\v!yes {
- \xmlconcat{#1}{/!mml:times}{\times}
- } {
- \doifelse\MMLtimes@@symbol{dot} {
- \xmlconcat{#1}{/!mml:times}{\cdot}
- } {
- \doifelse\MMLtimes@@symbol{times} {
- \xmlconcat{#1}{/!mml:times}{\times}
- } {
- \xmlall{#1}{/!mml:times}
- }
- }
- }
-\stopxmlsetups
-
-\setupMMLappearance[root][\c!symbol=\v!yes]
-
-\startxmlsetups mml:root
- \xmldoifelse {#1} {/mml:degree} {
- \root
- \doifnot\MMLrootsymbol\v!no{\MMLcreset\xmltext{#1}{/mml:degree}}
- \of
- } {
- \sqrt
- }
- {\MMLcreset\xmlall{#1}{/!(mml:degree\string|mml:root)}}
-\stopxmlsetups
-
-% gcd
-
-\startxmlsetups mml:gcd
- \begingroup
- \gcd\left(\MMLcreset\xmlconcat{#1}{/!mml:gcd}{\MMLseparator,}\right)
- \endgroup
-\stopxmlsetups
-
-% and or xor implies, not
-
-\startxmlsetups mml:and \xmlconcat{#1}{/!mml:and} {\wedge} \stopxmlsetups
-\startxmlsetups mml:or \xmlconcat{#1}{/!mml:or} {\vee} \stopxmlsetups
-\startxmlsetups mml:xor \xmlconcat{#1}{/!mml:xor} {\mathopnolimits{xor}} \stopxmlsetups
-\startxmlsetups mml:implies \xmlconcat{#1}{/!mml:implies}{\Rightarrow} \stopxmlsetups
-\startxmlsetups mml:not \neg \xmlall {#1}{/!mml:not} \stopxmlsetups
-
-% forall exists
-
-%D We need to shift left below rotated A.
-
-\startxmlsetups mml:forall
- \forall \negthinspace \xmlsetup{#1}{mml:forallexists}
-\stopxmlsetups
-
-\startxmlsetups mml:exists
- \exists \xmlsetup{#1}{mml:forallexists}
-\stopxmlsetups
-
-\def\mmlforallexistslist{mml:bvar\string|mml:forall\string|mml:exists\string|mml:condition}
-
-\startxmlsetups mml:forallexists
- \normalsubscript{\xmlconcat{#1}{/mml:bvar}{\MMLseparator,}}
- \xmldoifelse {#1} {/mml:condition} {
- \thickspace
- \begingroup
- \xmlfirst{#1}{/mml:condition}
- \endgroup
- \ifcase\xmlcount{#1}{/!(\mmlforallexistslist)}\relax
- % nothing
- \or
- % == snelle volgende
- \left\vert
- \MMLcreset \medspace \xmlconcat{#1}{/!(\mmlforallexistslist)}{}
- \right.
- \else
- % special case
- \left\vert
- \matrix {
- \xmlconcat{#1}{/!(\mmlforallexistslist)}{\hfill\crcr}
- }
- \right.
- \fi
- } {
- :\xmlfirst{#1}{/!(\mmlforallexistslist)}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:abs
- \left\vert \MMLcreset\xmlall{#1}{/!mml:abs} \right\vert
-\stopxmlsetups
-
-\startxmlsetups mml:conjugate % watch extra {}
- {\overline{\MMLcreset\xmlall{#1}{/!mml:conjugate}}}
-\stopxmlsetups
-
-\startxmlsetups mml:arg
- \mathopnolimits{arg} \left( \MMLcreset\xmlall{#1}{/!mml:arg} \right)
-\stopxmlsetups
-
-\startxmlsetups mml:real
- \Re \left( \MMLcreset \xmlall{#1}{/!mml:real} \right)
-\stopxmlsetups
-
-\startxmlsetups mml:imaginary
- \Im \ left( \MMLcreset \xmlall{#1}{/!mml:imaginary} \right)
-\stopxmlsetups
-
-\startxmlsetups mml:lcm
- \mathopnolimits{lcm} \left( \xmlconcat{#1}{/!mml:lcm}{\MMLseparator,} \right)
-\stopxmlsetups
-
-\startxmlsetups mml:floor
- \lfloor \xmlall{#1}{/!mml:floor} \rfloor
-\stopxmlsetups
-
-\startxmlsetups mml:ceiling
- \lceiling \xmlall{#1}{/!mml:ceiling} \rceiling
-\stopxmlsetups
-
-% relations
-
-% apply attr or eq
-
-\setupMMLappearance[relation][\c!align=\v!no]
-
-\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
-\startxmlsetups mml:gt \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:lt \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:geq \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:leq \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:equivalent \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:approx \xmlsetup{#1}{mml:relation} \stopxmlsetups
-\startxmlsetups mml:factorof \xmlsetup{#1}{mml:relation} \stopxmlsetups
-
-\startxmlsetups mml:relation
- \edef\mmlapplyaction{\xmlfilter{#1}{/*/name()}}
- \MMLcreset \xmlsetup{#1}{mml:relation:\xmlattdef{#1}{align}{\MMLrelationalign}}
-\stopxmlsetups
-
-\startxmlsetups mml:relation:default
- \xmlconcatrange{#1}{/*}{2}{}{\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}}
-\stopxmlsetups
-\startxmlsetups mml:relation:last
- \eqalign {
- \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}{[\mmlapplyaction]}{}
- &\xmlconcatrange{#1}{/*}{3}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&}
- }
-\stopxmlsetups
-\startxmlsetups mml:relation:left
- \eqalign {
- \xmlconcatrange{#1}{/*}{2}{}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr}
- }
-\stopxmlsetups
-\startxmlsetups mml:relation:right
- \eqalign {
- &\xmlconcatrange{#1}{/*}{2}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&}
- }
-\stopxmlsetups
-\startxmlsetups mml:relation:no
- \xmlsetup{#1}{mml:relation:default}
-\stopxmlsetups
-\startxmlsetups mml:relation:yes
- \xmlsetup{#1}{mml:relation:left}
-\stopxmlsetups
-
-% personal goody:
-
-\edef\MMLcmainresetlist{\MMLcmainresetlist\string|becomes}
-
-\xmlmapvalue {mml:relation} {mml:becomes} {:=}
-
-\startxmlsetups mml:becomes \xmlsetup{#1}{mml:relation} \stopxmlsetups
-
-% calculus and vector calculus
-
-\startxmlsetups mml:domainofapplication
- \xmlall{#1}{/!mml:domainofapplication}
-\stopxmlsetups
-
-\setupMMLappearance[int][\c!location=\v!top]
-
-\def\doMMLlimits#1{\doifelsevalue{MML#1\c!location}\v!top\limits\nolimits}
-
-\startxmlsetups mml:int
- \MMLcreset
- \xmldoifelse {#1} {/mml:domainofapplication} {
- \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:domainofapplication}}\relax
- } {
- \xmldoifelse {#1} {/mml:condition} {
- \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:condition}}\relax
- } {
- \xmldoifelse {#1} {/mml:lowlimit} {
- \int \doMMLlimits{int}\normalsubscript{\xmlfirst{#1}{/mml:lowlimit}}\normalsuperscript{\xmlfirst{#1}{/mml:uplimit}}
- } {
- % funny, why do we have lowlimit/uplimit then
- \xmldoifelse {#1} {/mml:apply/mml:interval} {
- \int \doMMLlimits{int}\normalsubscript{\xmlindex{#1}{/mml:apply}{2}}\normalsuperscript{\xmlindex{#1}{/mml:apply}{3}}
- } {
- \int
- }
- }
- }
- }
- \MMLcreset
- \xmldoifelse {#1} {/mml:apply} {
- \doifelsemmlfunction {#1} { % todo test
- \xmlfirst{#1}{/mml:apply}
- } {
- % if there are too many () now, we need to be more clever
- \left( \xmlfirst{#1}{/mml:apply} \right)
- }
- } {
- \xmlfirst{#1}{/mml:ci}
- }
- \xmldoifelse {#1} {/mml:bvar} {
- \thinspace {\mr d} \xmlfirst{#1}{/mml:bvar}
- } {
- % nothing
- }
-\stopxmlsetups
-
-\setupMMLappearance[diff][\c!location=\v!top,\c!alternative=\v!a]
-
-\startxmlsetups mml:diff
- \MMLcreset
- \doifelse \MMLdiffalternative \v!a {
- \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
- {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:ci}}
- \normalsuperscript
- {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}
- }
- } {
- \xmldoifelse {#1} {/mml:bvar} {
- \frac {
- {\mr d}{
- \xmldoifelse {#1} {/mml:degree} {
- \normalsuperscript{\xmlconcat{#1}{/mml:degree}\empty}
- } {
- \xmldoif {#1} {/mml:bvar/mml:degree} {
- \normalsuperscript{\xmlconcat{#1}{/mml:bvar/mml:degree}+}
- }
- }
- }
- \doif \MMLdifflocation \v!top {
- \xmldoifelse {#1} {/mml:ci} {
- \xmlfirst{#1}{/mml:ci}
- } {
- \MMLcreset
-\ifnum\xmlcount{#1}{/mml:apply/*}>\plustwo % hack
- \left(
- \xmlfirst{#1}{/mml:apply}
- \right)
-\else
- \xmlfirst{#1}{/mml:apply}
-\fi
- }
- }
- } {
- {\mr d}
- \xmlfirst{#1}{/mml:bvar/!mml:degree}
- \xmldoif {#1} {/mml:bvar/mml:degree} {
- \normalsuperscript{\xmlfirst{#1}{/mml:bvar/mml:degree}}
- }
- }
- \doifnot \MMLdifflocation \v!top {
- \left(\MMLcreset\xmlfirst{#1}{/(mml:apply\string|mml:ci)}\right)
- }
- } {
- % beware, the second {} is needed for the superscript
- \xmlconcatrange{#1}{/*}{2}{}{}\normalsuperscript\prime
- }
- }
- } {
- \MMLcreset
- \xmlfirst{#1}{/(mml:apply\string|mml:ci)}
- % there can be problems with nested diff's: \normalsuperscript\normalsuperscript{} error
- % so we add an empty group here
- {}\normalsuperscript
- {
- \xmldoifelse {#1} {/mml:degree} {
- \edef\mmldegree{\xmlfirst{#1}{/mml:degree/mml:cn}}
- \ifx\mmldegree\empty
- % what to do here
- \else
- \dorecurse\mmldegree\prime
- \fi
- } {
- \prime
- }
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:partialdiff
- \xmldoifelse {#1} {/mml:list} {
- {\mr D}\normalsubscript{
- \begingroup
- \setfalse\mmllistdelimiters
- \xmlall{#1}{/mml:list}
- \endgroup
- }
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
- } {
- \xmldoifelse {#1} {/mml:bvar} {
- \frac {
- {\mr d}\normalsuperscript{
- \xmldoifelse {#1} {/mml:degree} {
- \xmlconcat{#1}{/mml:degree}\empty
- } {
- \xmlconcat{#1}{/mml:bvar/mml:degree}+
- }
- }
- \MMLcreset
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
- } {
- \xmldoif {#1}{/mml:bvar/!mml:degree} {
- \xmlfirst{#1}{/mml:bvar/!mml:degree} \,
- }
- {\mr d}\xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
- \xmldoif {#1} {/mml:bvar/mml:degree} {
- \normalsuperscript{\xmlfirst{#1}{/mml:bvar/mml:degree}}
- }
- }
- } {
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:divergence \mathopnolimits{div} \xmlall{#1}{/!mml:divergence} \stopxmlsetups
-\startxmlsetups mml:grad \mathopnolimits{grad} \xmlall{#1}{/!mml:grad} \stopxmlsetups
-\startxmlsetups mml:curl \mathopnolimits{curl} \xmlall{#1}{/!mml:curl} \stopxmlsetups
-\startxmlsetups mml:laplacian \nabla\normalsuperscript2 \xmlall{#1}{/!mml:laplacian} \stopxmlsetups
-\startxmlsetups mml:ident \mathopnolimits{identity} \xmlall{#1}{/!mml:ident} \stopxmlsetups
-
-\setupMMLappearance[domain] [symbol=]
-\setupMMLappearance[codomain][symbol=]
-
-\startxmlsetups mml:domain
- \doifelsenothing \MMLdomainsymbol {
- \mathopnolimits{domain}\MMLcreset\xmlall{#1}{/!mml:domain}
- } {
- \MMLdomainsymbol\normalsubscript{\xmlall{#1}{/!mml:domain}}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:codomain
- \doifelsenothing \MMLcodomainsymbol {
- \mathopnolimits{codomain}\MMLcreset\xmlall{#1}{/!mml:codomain}
- } {
- \MMLcodomainsymbol\normalsubscript{\xmlall{#1}{/!mml:codomain}}
- }
-\stopxmlsetups
-
-% theory of sets
-
-\startxmlsetups mml:set
- \left\{
- \xmldoifelse {#1} {/mml:condition} {
- \xmlfirst{#1}{/mml:bvar}\,\middle\vert\,\xmlfirst{#1}{/mml:condition}
- } {
- \xmlconcat{#1}{/!mml:set}{\MMLseparator,}
- }
- \right\}
- \relax % needed
-\stopxmlsetups
-
-\settrue\mmllistdelimiters
-
-\startxmlsetups mml:list
- \begingroup
- \ifconditional\mmllistdelimiters\left [\fi
- \begingroup
- \settrue\mmllistdelimiters
- \xmlconcat{#1}{/!mml:list}{\MMLseparator,}
- \endgroup
- \ifconditional\mmllistdelimiters\right]\fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:union \mmlsecond{#1} \cup \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:intersect \mmlsecond{#1} \cap \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:in \mmlsecond{#1} \in \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:notin \mmlsecond{#1} {\not\in} \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:subset \mmlsecond{#1} \subset \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:prsubset \mmlsecond{#1} \subseteq \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:notsubset \mmlsecond{#1} {\not\subset} \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:notprsubset \mmlsecond{#1} {\not\subseteq} \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:setdiff \mmlsecond{#1} \setminus \mmlthird{#1} \stopxmlsetups
-
-\startxmlsetups mml:card
- \left\vert \xmlall{#1}{/!mml:card} \right\vert
-\stopxmlsetups
-
-\startxmlsetups mml:cartesianproduct
- \xmlconcat{#1}{/!mml:cartesianproduct}{\times}
-\stopxmlsetups
-
-% sequences and series
-
-\setupMMLappearance[sum] [\c!location=\v!top]
-\setupMMLappearance[product][\c!location=\v!top]
-
-\xmlmapvalue {mml:sumprod} {sum} {\sum}
-\xmlmapvalue {mml:sumprod} {product} {\prod}
-
-\startxmlsetups mml:sum \edef\mmlsumprodname{sum} \xmlsetup{#1}{mml:sumprod} \stopxmlsetups
-\startxmlsetups mml:product \edef\mmlsumprodname{product} \xmlsetup{#1}{mml:sumprod} \stopxmlsetups
-
-\def\mmlstackedsubscripts#1%
- {\vbox
- {\baselineskip\zeropoint % hack, taco vragen
- \halign{\startimath\scriptstyle\hss\alignmark\alignmark\hss\stopimath\cr#1\crcr}}}
-
-% unfinished
-
-\startxmlsetups mml:sumprod
- \begingroup
- \xmldoifelse {#1} {/(mml:condition\string|mml:bvar\string|mml:lowlimit)} {
- \def\mmlsumprodlower{
- \normalsubscript{
- \xmldoifelse {#1} {/mml:condition} {
- \mmlstackedsubscripts{\xmlconcat{#1}{/mml:condition}{\crcr}}
- } {
- \xmldoif {#1} {/mml:bvar} {
- \xmlfirst{#1}{/mml:bvar}
- \xmldoif{#1}{/mml:lowlimit}{=}
- }
- \xmlfirst{#1}{/mml:lowlimit}
- }
- }
- }
- } {
- \let\mmlsumprodlower\empty
- }
- \xmldoifelse {#1} {/mml:uplimit} {
- \def\mmlsumprodupper{\normalsuperscript{\xmlfirst{#1}{/mml:uplimit}}}
- } {
- \let\mmlsumprodupper\empty
- }
- \xmldoif {#1} {/mml:interval} { % open math converter gives this
- \edef\mmlintervalfrom{\xmlindex{#1}{/mml:interval}{1}}
- \edef\mmlintervalto {\xmlindex{#1}{/mml:interval}{2}}
- \ifx \mmlintervalfrom \empty \else
- \def\mmlsumprodlower{\normalsubscript{\xmldoif{#1}{/mml:bvar}{\xmlfirst{#1}{/mml:bvar}{=}}\mmlintervalfrom}}
- \fi
- \ifx \mmlintervalto \empty \else
- \def\mmlsumprodupper{\normalsuperscript{\mmlintervalto}}
- \fi
- }
- \MMLcreset
- \xmlval{mml:sumprod}{\mmlsumprodname}{}\doMMLlimits\mmlsumprodname\mmlsumprodupper\mmlsumprodlower
- \MMLcreset
- \xmldoifelse {#1} {/mml:lambda/mml:apply} {
- \xmlfirst{#1}{/mml:lambda/mml:apply}% a bit of open math conversion mess
- } {
- \xmlfirst{#1}{/(mml:apply\string|mml:lambda\string|mml:ci)}%
- }
- \endgroup
-\stopxmlsetups
-
-\setupMMLappearance[limit][\c!location=\v!top]
-
-\startxmlsetups mml:limit
- \MMLcreset \lim
- \doMMLlimits {limit}\normalsubscript{
- \MMLcreset
- \xmldoifelse {#1} {/mml:condition} {
- \xmlfirst{#1}{/mml:condition}
- } {
- \xmldoif {#1} {/mml:bvar} {
- \xmlfirst{#1}{/mml:bvar}\rightarrow
- }
- \xmlfirst{#1}{/mml:lowlimit}
- }
- }
- \begingroup
- % a bit of open math conversion mess, lambda needed for openmath, ok?
- \MMLcreset
- \xmlfirst{#1}{/mml:lambda/mml:apply}
- \xmlfirst{#1}{/(mml:apply\string|mml:lambda)}
- \endgroup
-\stopxmlsetups
-
-% consider a faster index
-
-\startxmlsetups mml:tendsto
- \MMLcreset \mmlsecond{#1}
- \xmlval {mml:tendsto:type} {\xmlattdef{#1}{type}{default}} {\rightarrow}
- \MMLcreset \mmlthird{#1}
-\stopxmlsetups
-
-\xmlmapvalue {mml:tendsto:type} {above} {\downarrow}
-\xmlmapvalue {mml:tendsto:type} {below} {\uparrow}
-\xmlmapvalue {mml:tendsto:type} {default} {\rightarrow}
-
-% elementary classical functions
-
-\setupMMLappearance[log][\c!location=\v!right]
-
-\startxmlsetups mml:exp
-% {\mr e}\normalsuperscript{\xmlfirst{#1}{/mml:apply\string|mml:reln\string|mml:ci\string|mml:cn}}
- {\mr e}\normalsuperscript{\xmlfirst{#1}{/!mml:exp}}
-\stopxmlsetups
-
-\startxmlsetups mml:log
- \xmldoifelse {#1} {/mml:logbase} {
- \doifelse \MMLloglocation \v!left {
- \mathop {
- {}\normalsuperscript{\xmlfirst{#1}{/mml:logbase}}\negthinspace\mathopnolimits{log}
- }
- } {
- \mathopnolimits{log}\normalsubscript{\xmlfirst{#1}{/mml:logbase}}
- }
-% \MMLcreset
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
-% \xmlsetup{#1}{mml:function} % todo, we start elsewhere
-% \mmlthird{#1}
- } {
- \mathopnolimits{log}
-% \MMLcreset
-% \xmlsetup{#1}{mml:function} % todo, we start elsewhere
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}
-% \mmlsecond{#1}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:ln
- \mathopnolimits{ln}
- \xmlsetup{#1}{mml:function}
-\stopxmlsetups
-
-% statistics
-
-\startxmlsetups mml:mean \overline {\mmlsecond{#1}} \stopxmlsetups
-\startxmlsetups mml:sdev \sigma \left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
-\startxmlsetups mml:variance \sigma \left(\MMLcreset\mmlsecond{#1}\right)\normalsuperscript2 \stopxmlsetups
-\startxmlsetups mml:median \mathopnolimits{median}\left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
-\startxmlsetups mml:mode \mathopnolimits{mode} \left(\MMLcreset\mmlsecond{#1}\right) \stopxmlsetups
-
-% moments
-
-\startxmlsetups mml:moment
- \left\langle
- \xmlfirst{#1}{/(mml:apply\string|mml:reln\string|mml:ci\string|mml:cn)}\normalsuperscript{\xmlfirst{#1}{/mml:degree}}
- \right\rangle
- \xmldoif {#1} {mml:momentabout} {
- \normalsubscript{\xmlfirst{#1}{mml:momentabout}}
- }
-\stopxmlsetups
-
-% linear algebra
-
-\setupMMLappearance [vector] [\c!direction=\v!horizontal,\c!separator={,}]
-
-\startxmlsetups mml:vector
- \begingroup
- \ifnum\xmlcount{#1}{/*}>\plusone
- \doifelse\MMLvectordirection\v!horizontal {
- \left(\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}\right)
- } {
- \MMLcreset\left(\matrix{\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}}\right)
- }
- \else
- \overrightarrow{\charhtstrut\mmlfirst{#1}}
- \fi
- \endgroup
-\stopxmlsetups
-
-\settrue\MMCdelmatrix % ( ) when true
-
-\startxmlsetups mml:matrix
- \begingroup
- \MMLcreset
- \ifconditional\MMCdelmatrix
- \left(\matrix{\xmlcommand{#1}{/mml:matrixrow}{mml:matrixrow:do}}\right)
- \else
- \settrue\MMCdelmatrix
- \matrix{\xmlcommand{#1}{/mml:matrixrow}{mml:matrixrow:do}}
- \fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:matrixrow
- \begingroup
- \MMLcreset
- \left(\xmlsetup{#1}{mml:matrixrow:do}\right)
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:matrixrow:do
- \xmlconcat{#1}{/*}{&}\crcr
-\stopxmlsetups
-
-\startxmlsetups mml:determinant
- \begingroup
- \setfalse\MMCdelmatrix
- \left|\mmlsecond{#1}\right|
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:transpose
- \mmlsecond{#1}\normalsuperscript{\mathopnolimits{T}}
-\stopxmlsetups
-
-\startxmlsetups mml:selector
- \MMLmathinner{\mmlsecond{#1}\normalsubscript{\MMLcreset\xmlconcatrange{#1}{/*}{3}{}{\MMLseparator,}}}
-\stopxmlsetups
-
-\startxmlsetups mml:vectorproduct \mmlsecond{#1}\times \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:scalarproduct \mmlsecond{#1}\cdot \mmlthird{#1} \stopxmlsetups
-\startxmlsetups mml:outerproduct \mmlsecond{#1}\otimes\mmlthird{#1} \stopxmlsetups
-
-% semantic mapping elements
-
-\setupMMLappearance[semantics][\c!state=\v!start]
-
-\startxmlsetups mml:semantics
- \doifelse\MMLsemanticsstate\v!start {
- \xmlall{#1}{/mml:annotation}
- } {
- \xmlall{#1}{/!mml:annotation}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:annotation
- \xmldoifelse {#1} {.[oneof(@encoding,'TeX','tex','TEX','ConTeXt','context','CONTEXT','ctx')]} {
- \xmlflushcontext{#1}
- } {
- \xmldoifelse {#1} {.[oneof(@encoding,'calcmath','cm')]} {
- \expanded{\calcmath{\xmlflush{#1}}}
- } {
- \xmldoifelse {#1} {.[oneof(@encoding,'asciimath','am')]} {
- \ifdefined\asciimath
- \expanded{\asciimath{\xmlflush{#1}}}
- \else
- \hbox{\tt no am loaded}%
- \fi
- } {
- \xmlall{#1}{../!mml:annotation}
- }
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:annotation-xml
- % maybe diagnostics
-\stopxmlsetups
-
-% misc
-
-\startxmlsetups mml:integers \integers \stopxmlsetups
-\startxmlsetups mml:reals \reals \stopxmlsetups
-\startxmlsetups mml:rationals \rationals \stopxmlsetups
-\startxmlsetups mml:naturalnumbers \naturalnumbers \stopxmlsetups
-\startxmlsetups mml:complexes \complexes \stopxmlsetups
-\startxmlsetups mml:primes \primes \stopxmlsetups
-\startxmlsetups mml:exponentiale \mathopnolimits{e} \stopxmlsetups
-\startxmlsetups mml:imaginaryi \mathopnolimits{i} \stopxmlsetups
-\startxmlsetups mml:notanumber \mathopnolimits{NaN} \stopxmlsetups
-\startxmlsetups mml:true \mathopnolimits{true} \stopxmlsetups
-\startxmlsetups mml:false \mathopnolimits{false} \stopxmlsetups
-\startxmlsetups mml:emptyset \mathopnolimits{\O} \stopxmlsetups
-\startxmlsetups mml:pi \pi \stopxmlsetups
-\startxmlsetups mml:eulergamma \gamma \stopxmlsetups
-\startxmlsetups mml:infinity \infty \stopxmlsetups
-
-% gonio functions
-
-\setupMMLappearance[function][\c!reduction=\v!yes]
-
-% todo: \mfunction which adapts itself when registered as command
-
-% todo: \def\mmlcfunction#1#2{\mathopnolimits{#2}\xmlsetup{#1}{mml:function}}
-
-\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
- \ifconditional\xmlinversefunction\normalsuperscript{-1}\fi
- \setfalse\xmlinversefunction
- \else
- \normalsuperscript{\ifconditional\xmlinversefunction-\fi\MMLpowerelement}
- \setfalse\xmlinversefunction
- \glet\MMLpowerelement\empty
- \fi
- \xmlsetup{#1}{mml:function:argument}
-\stopxmlsetups
-
-\startxmlsetups mml:function:argument
- \doifelse \MMLfunctionreduction \v!yes {
- \xmldoifelse {#1} {/mml:apply} {
- \xmldoifelse {#1} {/mml:apply/(\MMLcfunctionlist\string|mml:divide)}
- \donefalse
- \donetrue
- } {
- \donefalse
- }
- } {
- \donetrue
- }
- % beware, we still flush from 2 up
- \ifdone
- \left(
- \MMLcreset
- \xmlall{#1}{/[position()>1]}% \xmlconcatrange{#1}{/*}{2}{}\empty
- \right)
- \else
- \MMLcreset
- \xmlall{#1}{/[position()>1]}
- \fi
-\stopxmlsetups
-
-% PRESENTATION MATHML
-%
-% there are some rough edges that need to be sorted out
-
-% helpers
-
-\xmlmapvalue {mml} {normal} {\tf}
-\xmlmapvalue {mml} {double-struck} {\bf}
-\xmlmapvalue {mml} {italic} {\it}
-\xmlmapvalue {mml} {fraktur} {\bf}
-\xmlmapvalue {mml} {script} {\tf}
-\xmlmapvalue {mml} {bold} {\bf}
-\xmlmapvalue {mml} {bold-italic} {\bi}
-\xmlmapvalue {mml} {bold-fraktur} {\bf}
-\xmlmapvalue {mml} {bold-script} {\bf}
-\xmlmapvalue {mml} {sans-serif} {\ss}
-\xmlmapvalue {mml} {bold-sans-serif} {\ss\bf}
-\xmlmapvalue {mml} {sans-serif-italic} {\ss\it}
-\xmlmapvalue {mml} {sans-serif-bold-italic} {\ss\bi}
-\xmlmapvalue {mml} {monospace} {\tt}
-
-% todo: displaystyle=true/false (or whatever else shows up)
-
-\starttexdefinition setmmlmathstyle #1
- \xmlval {mml} {\xmlatt{#1}{mathvariant}} \empty % was: \mmmr
-\stoptexdefinition
-
-\starttexdefinition applymmlmathcolor #1#2
- \edef\mmlmathcolor{\xmlatt{#1}{mathcolor}}
- \ifx \mmlmathcolor \empty
- #2
- \else
- \color[\mmlmathcolor]{#2}
- \fi
-\stoptexdefinition
-
-% todo: textbackgrounds
-
-\starttexdefinition applymmlmathbackground #1#2
- \edef\mmlmathbackground{\xmlatt{#1}{mathbackground}}
- \ifx \mmlmathbackground \empty
- #2
- \else
- \backgroundline[\mmlmathbackground]{#2}
- \fi
-\stoptexdefinition
-
-\newsignal\mmltextsignal % not used
-
-\starttexdefinition applymmlsometext #1#2
- \applymmlmathbackground {#1} {
- \applymmlmathcolor {#1} {
- \setmmlmathstyle {#1}
- #2
- }
- }
-\stoptexdefinition
-
-% probably bugged:
-
-\starttexdefinition doMMLfiller #1
- \pushmacro\doMMLfiller
- \let\doMMLfiller\gobbleoneargument
- \gdef\dodoMMLfiller{% where used
- \disablefiller
- \mathematics{#1}
- }
- \hbox {
- \def\normalorfiller##1##2{
- \gdef\dodoMMLfiller{\enablefiller#1}%
- \let\normalorfiller\gobbletwoarguments
- }
- \mathematics{#1}
- }
- \popmacro\doMMLfiller
-\stoptexdefinition
-
-% setups
-
-\startxmlsetups mml:mi % todo: mathvariant mathsize mathcolor mathbackground
- \ctxmodulemathml{mi("#1")}
-\stopxmlsetups
-
-\startxmlsetups mml:mn % todo: mathvariant mathsize mathcolor mathbackground
-% \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>
-%
-% spacing between - and 2 is taken care of by tex itself
-
-\startxmlsetups mml:mo
- \doif {\xmlatt{#1}{maxsize}} {1} {\settrue\mmlignoredelimiter}
- \doif {\xmlatt{#1}{stretchy}} {false} {\settrue\mmlignoredelimiter}
- \ctxmodulemathml{mo("#1")}
- \setfalse\mmlignoredelimiter
-\stopxmlsetups
-
-\startxmlsetups mml:mfenced % {} around separator is needed for spacing
- \def\MMLleft {\left }% weird
- \def\MMLright {\right}
- \def\MMLmiddle{\middle}
- \ctxmodulemathml{mfenced("#1")}
-\stopxmlsetups
-
-\defineoverlay [mml:enclose:box] [\useMPgraphic{mml:enclose:box}]
-\defineoverlay [mml:enclose:roundedbox] [\useMPgraphic{mml:enclose:roundedbox}]
-\defineoverlay [mml:enclose:circle] [\useMPgraphic{mml:enclose:circle}]
-\defineoverlay [mml:enclose:left] [\useMPgraphic{mml:enclose:left}]
-\defineoverlay [mml:enclose:right] [\useMPgraphic{mml:enclose:right}]
-\defineoverlay [mml:enclose:top] [\useMPgraphic{mml:enclose:top}]
-\defineoverlay [mml:enclose:bottom] [\useMPgraphic{mml:enclose:bottom}]
-\defineoverlay [mml:enclose:updiagonalstrike] [\useMPgraphic{mml:enclose:updiagonalstrike}]
-\defineoverlay [mml:enclose:downdiagonalstrike] [\useMPgraphic{mml:enclose:downdiagonalstrike}]
-\defineoverlay [mml:enclose:horizontalstrike] [\useMPgraphic{mml:enclose:horizontalstrike}]
-\defineoverlay [mml:enclose:verticalstrike] [\useMPgraphic{mml:enclose:verticalstrike}]
-
-\startuseMPgraphic{mml:enclose:box}
- draw OverlayBox withpen pencircle scaled (ExHeight/10) ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:roundedbox}
- draw OverlayBox cornered .5ExHeight withpen pencircle scaled (ExHeight/10) ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:circle}
- draw fullcircle xysized(bbwidth(OverlayBox),bbheight(OverlayBox)) withpen pencircle scaled (ExHeight/10) ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:left}
- draw leftboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:right}
- draw rightboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:top}
- draw topboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:bottom}
- draw bottomboundary OverlayBox withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:updiagonalstrike}
- path p ; p := OverlayBox enlarged -.25ExHeight ;
- draw llcorner p -- urcorner p withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:downdiagonalstrike}
- path p ; p := OverlayBox enlarged -.25ExHeight ;
- draw ulcorner p -- lrcorner p withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:horizontalstrike}
- path p ; p := OverlayBox enlarged -.25ExHeight ;
- draw .5[llcorner p,ulcorner p] -- .5[lrcorner p,urcorner p] withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-\startuseMPgraphic{mml:enclose:verticalstrike}
- path p ; p := OverlayBox enlarged -.25ExHeight ;
- draw .5[llcorner p,lrcorner p] -- .5[ulcorner p,urcorner p] withpen pencircle scaled (ExHeight/10) ;
- setbounds currentpicture to OverlayBox ;
-\stopuseMPgraphic
-
-\startxmlsetups mml:menclose
- \edef\mmlmenclosenotation{\ctxmodulemathml{menclosepattern("#1")}}
- \ifx\mmlmenclosenotation\empty
- \xmlflush{#1}
- \else
- \doifelse \mmlmenclosenotation {mml:enclose:longdiv} {
- \overline{\left)\strut\xmlflush{#1}\right.}
- } {
- \doifelse \mmlmenclosenotation {mml:enclose:actuarial} {
- \overline{\left.\strut\xmlflush{#1}\right|}
- } {
- \doifelse \mmlmenclosenotation {mml:enclose:radical} {
- \sqrt{\xmlflush{#1}}
- } {
- % todo: no framed when longdiv, actuarial or radical ? spec ?
- \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.}
- } {
- \expanded{\doifinsetelse {mml:enclose:actuarial} {\mmlmenclosenotation}} {
- \overline{\left.\strut\xmlflush{#1}\right|}
- } {
- \expanded{\doifinsetelse {mml:enclose:radical} {\mmlmenclosenotation}} {
- \sqrt{\xmlflush{#1}}
- } {
- \xmlflush{#1}
- }
- }
- }
- \stopimath}
- }
- }
- }
- }
- \fi
-\stopxmlsetups
-
-\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
- \edef\mmlfraclinethickness{\xmlatt{#1}{linethickness}}
- \ifx\mmlfraclinethickness\empty
- \doifelse{\xmlatt{#1}{bevelled}}{true} {
- \left.\mmlfirst{#1}\middle/\mmlsecond{#1}\right.% \thinspace\middle/\thinspace
- } {
- \frac{\mmlfirst{#1}}{\mmlsecond{#1}}
- }
- \else
- \doifelse {\xmlval{mml:mfrac:linethickness}{\mmlfraclinethickness}{}} {} {
- \scratchdimen\xmlval{mml:mfrac:linethickness}\mmlfraclinethickness{.4pt}
- } {
- % probably not yet ok
- \setdimensionwithunit\scratchdimen\mmlfraclinethickness{pt}
- }
- {
- {\mmlfirst{#1}}
- \above\scratchdimen
- {\mmlsecond{#1}}
- }
- \fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:ms
- \hbox {
- \tf % else encoding problems
- \edef\mmllquote{\xmlatt{#1}{lquote}}
- \edef\mmlrquote{\xmlatt{#1}{rquote}}
- \ifx\mmllquote\empty\symbol[leftquotation]\else\mmllquote\fi
- \applymmlsometext{#1}{\xmlflush{#1}}
- \ifx\mmlrquote\empty\symbol[rightquotation]\else\mmlrquote\fi
- }
-\stopxmlsetups
-
-\startxmlsetups mml:mstyle
- \begingroup
- \setmmlmathstyle{#1}
- \xmlflush{#1}
- \endgroup
-\stopxmlsetups
-
-\setupMMLappearance[text][\c!alternative=\v!b] % a=normal, b=keep spaces
-
-\startxmlsetups mml:mtext
- \text {
- \applymmlsometext{#1}{
- \doifelse \MMLtextalternative \v!a {
- %\ctxmodulemathml{stripped(\!!bs\xmlflush{#1}\!!es)}
- \ignorespaces
- \xmlflush{#1}
- \removeunwantedspaces
- } {
- \xmlflush{#1}
- }
- }
- }
-\stopxmlsetups
-
-\startxmlsetups mml:merror
- \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{\triggermathstyle\normalmathstyle\ignorespaces\xmlflush{#1}\removeunwantedspaces}
-% \mktriggereffect\v!hidden
-% \ignorespaces{}\xmlflush{#1}\unskip % no attributes in math yet
-% \mktriggereffect\v!normal
-\stopxmlsetups
-
-\startxmlsetups mml:mpadded % todo
- \xmlflush{#1}
-\stopxmlsetups
-
-% mrow / option: no fenced
-
-\startxmlsetups mml:maction
- \xmlflush{#1}
-\stopxmlsetups
-
-\startxmlsetups mml:mrow
- \begingroup
- \edef\nofmmlrows{\xmlcount{#1}{/mml:mo}}%
- \ifnum\nofmmlrows=\plustwo
- \xmldoifelse {#1} {/mml:mo[position()==1 or position()==\nofmmlrows]} {% we need a {}
- \def\MMLleft {\left }
- \def\MMLright {\right}
- \def\MMLmiddle{\middle}
- \enabledelimiter
- \checkdelimiters{\xmlall{#1}{/mml:mo}}
- \fakeleftdelimiter
- \xmlflush{#1}
- \fakerightdelimiter
- \disabledelimiter
- } {
- \xmlflush{#1}
- }
- \else
- \xmlflush{#1}
- \fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:msqrt
- \sqrt{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups mml:mroot
- \root{\mmlsecond{#1}}\of{\mmlfirst{#1}}
-\stopxmlsetups
-
-\setupMMLappearance[scripts][\c!alternative=\v!a] % {} rond base
-
-\startxmlsetups mml:msub
- \doifelse\MMLscriptsalternative\v!a {
- {\mmlfirst{#1}}\normalsubscript{\mmlsecond{#1}}
- } {
- \mmlfirst{#1} \normalsubscript{\mmlsecond{#1}}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:msup
- \doifelse\MMLscriptsalternative\v!a {
- {\mmlfirst{#1}}\normalsuperscript{\mmlsecond{#1}}
- } {
- \mmlfirst{#1} \normalsuperscript{\mmlsecond{#1}}
- }
-\stopxmlsetups
-
-\startxmlsetups mml:msubsup
- \doifelse\MMLscriptsalternative\v!a {
- {\mmlfirst{#1}}\normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}}
- } {
- \mmlfirst{#1} \normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}}
- }
-\stopxmlsetups
-
-\def\mmlexecuteifdefined#1%
- {\ifx#1\empty
- \expandafter\secondoftwoarguments
- \else\ifcsname#1\endcsname
- \expandafter\expandafter\expandafter\firstoftwoarguments
- \else
- \expandafter\expandafter\expandafter\secondoftwoarguments
- \fi\fi
- {\csname#1\endcsname}}
-
-\startxmlsetups mml:mover
-% \mathop {
- \edef\mmlovertoken{\xmlraw{#1}{/mml:*[2]}}
- \doifelse{\utfmathclass\mmlovertoken}{accent} {
- \edef\mmlovercommand{\utfmathcommand\mmlovertoken}
- \mmlexecuteifdefined\mmlovercommand\mathematics{\mmlfirst{#1}}
- } {
- \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}}
- \edef\mmlbasecommand{\utfmathfiller\mmlbasetoken}
- \edef\mmlovercommand{\utfmathfiller\mmlovertoken}
- \vbox {
- \mathsurround\zeropoint \ialign {
- \hss##\hss\crcr
- \noalign{\kern3\onepoint}%
- \mmlexecuteifdefined\mmlovercommand{\mathematics{\mmlsecond{#1}}}\crcr
- \noalign{\kern3\onepoint\nointerlineskip}%
- \mmlexecuteifdefined\mmlbasecommand{\mathematics{\mmlfirst{#1}}}\crcr
- }
- }
- }
-% }
-% \limits % spoils spacing
-\stopxmlsetups
-
-\startxmlsetups mml:munder
-% \mathop {
- \edef\mmlundertoken{\xmlraw{#1}{/mml:*[2]}}
- \doifelse{\utfmathclass\mmlundertoken}{accent} {
- \edef\mmlundercommand{\utfmathcommand\mmlundertoken}
- \mmlexecuteifdefined\mmlundercommand\mathematics{\mmlfirst{#1}}
- } {
- \edef\mmlbasetoken {\xmlraw{#1}{/mml:*[1]}}
- \edef\mmlbasecommand {\utfmathfiller\mmlbasetoken}
- \edef\mmlundercommand{\utfmathfiller\mmlundertoken}
- \vtop {
- \mathsurround\zeropoint \ialign {
- \hss##\hss\crcr
- \mmlexecuteifdefined\mmlbasecommand {\mathematics{\mmlfirst{#1}}}\crcr
- \noalign{\kern3\onepoint\nointerlineskip}%
- \mmlexecuteifdefined\mmlundercommand{\mathematics{\mmlsecond{#1}}}\crcr
- \noalign{\kern3\onepoint}
- }
- }
- }
-% }
-% \limits % spoils spacing
-\stopxmlsetups
-
-\startxmlsetups mml:munderover
- \edef\mmlbasetoken{\xmlraw{#1}{/mml:*[1]}}
- \edef\mmlbasecommand{\utfmathcommand\mmlbasetoken}
- \mmlexecuteifdefined\mmlbasecommand{\mathematics{\mmlfirst{#1}}}\normalsubscript{\mmlsecond{#1}}\normalsuperscript{\mmlthird{#1}}
-\stopxmlsetups
-
-% tables (mml:mtable, mml:mtr, mml:mlabledtr, mml:mtd)
-
-\startxmlsetups mml:mtable % some more attributes need to be supported
- \vcenter{\ctxmodulemathml{mtable("#1")}}
-\stopxmlsetups
-
-\startxmlsetups mml:mcolumn
- \ctxmodulemathml{mcolumn("#1")}
-\stopxmlsetups
-
-\def\mmlsetfakewidth#1{\setbox\scratchbox\hbox{#1}\scratchdimen\wd\scratchbox}
-
-\def\mmlmcolumndigitspace {\mmlsetfakewidth {0}\kern\scratchdimen}
-\def\mmlmcolumndigitrule {\mmlsetfakewidth {0}\vrule width \scratchdimen height .2pt depth .2pt\relax}
-\def\mmlmcolumnsymbolrule {\mmlsetfakewidth{\times}\vrule width \scratchdimen height .2pt depth .2pt\relax}
-\def\mmlmcolumnpunctuationrule{\mmlsetfakewidth {.}\vrule width \scratchdimen height .2pt depth .2pt\relax}
-
-\startxmlsetups mml:mspace
- \begingroup
- \edef\mmlspacetext{\xmlatt{#1}{spacing}}
- \ifx\mmlspacetext\empty
- \!!widtha \xmlattdef{#1}{width} \!!zeropoint % must be string
- \!!heighta\xmlattdef{#1}{height}\!!zeropoint
- \!!deptha \xmlattdef{#1}{depth} \!!zeropoint
- \ifdim\!!heighta=\zeropoint
- \ifdim\!!deptha=\zeropoint\else
- \hbox{\vrule\!!depth\!!deptha\!!height\zeropoint\!!width\zeropoint}%
- \fi
- \else
- \hbox{\vrule\!!depth\zeropoint\!!height\!!heighta\!!width\zeropoint}%
- \fi
- \ifdim\!!widtha=\zeropoint\else
- \hskip\!!widtha
- \fi
- \else
- \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: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}}
- \edef\mmlglyphindex {\xmlatt {#1}{index}}
- \ifx \mmlglyphfontfamily \empty
- \hbox{\tttf[no fontfamily specified for \mmlglyphalt]}
- \else\ifx\mmlglyphindex\empty
- \hbox{\tttf[no index specified for \mmlglyphalt]}
- \else
- \hbox{\getglyph\mmlglyphfontfamily\mmlglyphindex}
- \fi\fi
- \endgroup
-\stopxmlsetups
-
-\startxmlsetups mml:maligngroup \stopxmlsetups % will be done when needed
-\startxmlsetups mml:malignmark \stopxmlsetups % will be done when needed
-
-\startxmlsetups mml:none \stopxmlsetups
-\startxmlsetups mml:mprescripts \stopxmlsetups
-
-\startxmlsetups mml:mmultiscripts
- \ctxmodulemathml{mmultiscripts("#1")}
-\stopxmlsetups
-
-% goodie
-
-\definebuffer[mml]
-
-\def\stopmml{\xmlprocessbuffer{@mml@}{\thedefinedbuffer{mml}}{}}
-
-\stopmodule
-
-\protect \endinput
-
-% TODO:
-%
-% <apply><divide/>
-% <apply><minus/>
-% <apply><minus/><ci>b</ci></apply>
-% <apply><minus/><ci>b</ci></apply>
-% <apply><root/> <ci>a</ci></apply>
-% </apply>
-% <apply><minus/>
-% <apply><minus/><ci>b</ci><ci>b</ci></apply>
-% <apply><minus/><ci>b</ci></apply>
-% <apply><root/> <ci>a</ci></apply>
-% </apply>
-% </apply>
-
-% \startmoduletestsection
-%
-% \def\xflushXMLstackwith#1#2#3#4% num bgroup egroup whatever
-% {\dostepwiserecurse{#1}\XMLstacklevel\plusone
-% {#2\relax
-% \ifnum\recurselevel>#1\relax#4\fi
-% \getXMLstackdata\recurselevel
-% #3}}
-%
-% \def\xflushXMLstackfrom#1#2#3%
-% {\dostepwiserecurse{#1}\XMLstacklevel\plusone
-% {#2\getXMLstackdata\recurselevel#3}}
-%
-% \startxmlsetups mml:minus
-% \doif \MMLsignreduction \v!yes {
-% \setMMLcreset{fn,\MMLcfunctionlist}
-% }
-% \ifcase\XMLstacklevel
-% \or
-% % self
-% \or
-% -\getXMLstackdata\plustwo
-% \else
-% \dostepwiserecurse \plustwo \XMLstacklevel \plusone {
-% \begingroup
-% \doifelse {\getXMLstackname\recurselevel} {apply} {
-% \ifnum\recurselevel=\plustwo
-% \begingroup
-% \dodoifelseMMCfunctioninapply \recurselevel {minus} {
-% \ifnum\XMLstacklevel>\plustwo
-% \endgroup
-% \else
-% \endgroup
-% \MMLcreset
-% \fi
-% } {
-% \endgroup
-% }
-% \else
-% \doifelseMMCfunctioninapply \recurselevel {\MMLcfunctionlist,\MMLcconstructlist} {
-% \MMLcreset
-% } {
-% }
-% \fi
-% } {
-% }
-% \getXMLstackdata\recurselevel
-% \ifnum\recurselevel<\XMLstacklevel\relax
-% -
-% \fi
-% \endgroup
-% }
-% \fi
-% \stopxmlsetups
-%
-% \stopmoduletestsection
diff --git a/tex/context/base/x-udhr.mkiv b/tex/context/base/x-udhr.mkiv
index 81075ac70..e081bfd59 100644
--- a/tex/context/base/x-udhr.mkiv
+++ b/tex/context/base/x-udhr.mkiv
@@ -87,7 +87,7 @@
\setuptolerance
[verytolerant]
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{x-udhr.mkiv}
% todo: when argument given then process it
diff --git a/tex/context/base/x-xfdf.mkiv b/tex/context/base/x-xfdf.mkiv
new file mode 100644
index 000000000..460220ed9
--- /dev/null
+++ b/tex/context/base/x-xfdf.mkiv
@@ -0,0 +1,72 @@
+%D \module
+%D [ file=x-xfdf,
+%D version=2011.09.07,
+%D title=\CONTEXT\ XML Modules,
+%D subtitle=\XFDF,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is a revival of using \XFDF, but now in a more \MKIV-ish way. We
+%D supported it long ago already in \MKII\ but never used it at a large
+%D scale (not that much user interest anyway).
+
+\startmodule[xfdf]
+
+% see xfdf-001.xfdf and xfdf-001.tex
+
+% %D Possible speedup but hardly worth the trouble.
+%
+% \startluacode
+%
+% local hashes = { } table.setmetatableindex(hashes,function(t,k) local v = { } t[k] = v return v end)
+%
+% function xml.functions.xfdf_collect_values(root)
+% local hash = hashes[root]
+% for c in xml.collected(root,"/xfdf/fields/field/value") do
+% hash[xml.parent(c).at.name] = c
+% end
+% end
+%
+% function xml.functions.xfdf_get_values(root,name)
+% return hashes[root][name]
+% end
+%
+% function lxml.xfdf_get_values(root,name)
+% xml.sprint(hashes[lxml.id(root)][name])
+% end
+%
+% \stopluacode
+%
+% \def\xfdfvalue#1#2%
+% {\ctxlua{lxml.xfdf_get_values("#1","#2")}}
+
+\startxmlsetups xfdf:define
+ \xmlsetsetup{#1}{*}{xfdf:*}
+ % \xmlfilter {#1}{./function(xfdf_collect_values)}
+\stopxmlsetups
+
+\xmlregisterns{xfdf}{http://ns.adobe.com/xfdf/}
+
+\xmlregisterdocumentsetup{xfdf}{xfdf:define}
+
+\startxmlsetups xfdf:value
+ \xmlflush{#1}
+\stopxmlsetups
+
+\def\xfdfload #1#2{\xmlloadonly{#1}{#2}{xfdf}}
+\def\xfdfvalue#1#2{\xmlfirst{#1}{/xfdf/fields/field[@name='#2']/value}}
+\def\xfdftext #1#2{\xmlfirst{#1}{/xfdf/fields/field[@name='#2']/value/paragraphs()}}
+
+% \startxmlsetups xfdf:b
+% \bold{\xmlflush{#1}}
+% \stopxmlsetups
+
+% \xfdfload {whatever}{xfdf-001.xfdf}
+% \xfdfvalue{whatever}{somefield}
+
+\stopmodule
diff --git a/tex/context/base/xtag-ini.mkii b/tex/context/base/xtag-ini.mkii
index 8f10c4f55..ce3cbacd0 100644
--- a/tex/context/base/xtag-ini.mkii
+++ b/tex/context/base/xtag-ini.mkii
@@ -395,22 +395,22 @@
% \def\disableXML
% {\setnormalcatcodes\processingXMLfalse}
-\defcatcodecommand\xmlcatcodese `\& \doXMLentity
-\defcatcodecommand\xmlcatcodese `\< \doXMLelement
-\defcatcodecommand\xmlcatcodesr `\& \doXMLentity
-\defcatcodecommand\xmlcatcodesr `\< \doXMLelement
-\defcatcodecommand\xmlcatcodesn `\& \doXMLentity
-\defcatcodecommand\xmlcatcodesn `\< \doXMLelement
-
-\letcatcodecommand\xmlcatcodesr `\# \letterhash
-\letcatcodecommand\xmlcatcodesr `\$ \letterdollar
-\letcatcodecommand\xmlcatcodesr `\% \letterpercent
-\letcatcodecommand\xmlcatcodesr `\\ \letterbackslash
-\letcatcodecommand\xmlcatcodesr `\^ \letterhat
-\letcatcodecommand\xmlcatcodesr `\_ \letterunderscore
-\letcatcodecommand\xmlcatcodesr `\{ \letterleftbrace
-\letcatcodecommand\xmlcatcodesr `\} \letterrightbrace
-\letcatcodecommand\xmlcatcodesr `\| \letterbar
+\defcatcodecommand\xmlcatcodese 046 \doXMLentity
+\defcatcodecommand\xmlcatcodese 060 \doXMLelement
+\defcatcodecommand\xmlcatcodesr 046 \doXMLentity
+\defcatcodecommand\xmlcatcodesr 060 \doXMLelement
+\defcatcodecommand\xmlcatcodesn 046 \doXMLentity
+\defcatcodecommand\xmlcatcodesn 060 \doXMLelement
+
+\letcatcodecommand\xmlcatcodesr 035 \letterhash
+\letcatcodecommand\xmlcatcodesr 036 \letterdollar
+\letcatcodecommand\xmlcatcodesr 037 \letterpercent
+\letcatcodecommand\xmlcatcodesr 092 \letterbackslash
+\letcatcodecommand\xmlcatcodesr 094 \letterhat
+\letcatcodecommand\xmlcatcodesr 095 \letterunderscore
+\letcatcodecommand\xmlcatcodesr 123 \letterleftbrace
+\letcatcodecommand\xmlcatcodesr 125 \letterrightbrace
+\letcatcodecommand\xmlcatcodesr 124 \letterbar
\bgroup \catcode`\&=13 \let&\relax
@@ -426,15 +426,15 @@
\egroup
-\letcatcodecommand\xmlcatcodese `\# \entityhash
-\letcatcodecommand\xmlcatcodese `\$ \entitydollar
-\letcatcodecommand\xmlcatcodese `\% \entitypercent
-\letcatcodecommand\xmlcatcodese `\\ \entitybackslash
-\letcatcodecommand\xmlcatcodese `\^ \entityhat
-\letcatcodecommand\xmlcatcodese `\_ \entityunderscore
-\letcatcodecommand\xmlcatcodese `\{ \entityleftbrace
-\letcatcodecommand\xmlcatcodese `\} \entityrightbrace
-\letcatcodecommand\xmlcatcodese `\| \entitybar
+\letcatcodecommand\xmlcatcodese 035 \entityhash
+\letcatcodecommand\xmlcatcodese 036 \entitydollar
+\letcatcodecommand\xmlcatcodese 037 \entitypercent
+\letcatcodecommand\xmlcatcodese 092 \entitybackslash
+\letcatcodecommand\xmlcatcodese 094 \entityhat
+\letcatcodecommand\xmlcatcodese 095 \entityunderscore
+\letcatcodecommand\xmlcatcodese 123 \entityleftbrace
+\letcatcodecommand\xmlcatcodese 125 \entityrightbrace
+\letcatcodecommand\xmlcatcodese 124 \entitybar
% we speed things up by explicitly setting the active char's < &
diff --git a/tex/context/base/xtag-pre.mkii b/tex/context/base/xtag-pre.mkii
index 63706d64c..5e75197b7 100644
--- a/tex/context/base/xtag-pre.mkii
+++ b/tex/context/base/xtag-pre.mkii
@@ -18,6 +18,19 @@
\unprotect
+%D For \MKIV:
+
+\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}}
+
+\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}%
+ \afterassignment\@@dowithgrabbedstring\grabstring}
+
%D Let's get rid of ligatures:
% \definefonthandling [default] [noligs]
diff --git a/tex/context/fonts/demo.lfg b/tex/context/fonts/demo.lfg
index 00ca3ee6e..06c59e644 100644
--- a/tex/context/fonts/demo.lfg
+++ b/tex/context/fonts/demo.lfg
@@ -30,11 +30,36 @@ return {
comment = "An example of goodies.",
author = "Hans Hagen",
featuresets = {
+ simple = {
+ mode = "node",
+ script = "latn"
+ },
default = {
- default,
+ mode = "node",
+ script = "latn",
+ kern = "yes",
+ },
+ ligatures = {
+ mode = "node",
+ script = "latn",
+ kern = "yes",
+ liga = "yes",
},
smallcaps = {
- default, smallcaps,
+ mode = "node",
+ script = "latn",
+ kern = "yes",
+ smcp = "yes",
+ },
+ },
+ solutions = { -- here we have references to featuresets, so we use strings!
+ experimental = {
+ less = {
+ "ligatures", "simple",
+ },
+ more = {
+ "smallcaps",
+ },
},
},
colorschemes = {
diff --git a/tex/context/fonts/husayni.lfg b/tex/context/fonts/husayni.lfg
index ff456f63c..2f45add21 100644
--- a/tex/context/fonts/husayni.lfg
+++ b/tex/context/fonts/husayni.lfg
@@ -17,6 +17,7 @@ local regular = {
ss01 = yes, ss03 = yes, ss07 = yes, ss10 = yes, ss12 = yes, ss15 = yes, ss16 = yes,
ss19 = yes, ss24 = yes, ss25 = yes, ss26 = yes, ss27 = yes, ss31 = yes, ss34 = yes,
ss35 = yes, ss36 = yes, ss37 = yes, ss38 = yes, ss41 = yes, ss42 = yes, ss43 = yes,
+ ss55 = yes,
js16 = yes,
}
@@ -31,6 +32,7 @@ local minimal_stretching = {
local medium_stretching = {
js12=yes, js05=yes,
}
+
local maximal_stretching= {
js13 = yes, js05 = yes, js09 = yes,
}
@@ -43,7 +45,7 @@ local shrink = {
flts = yes, js17 = yes, ss05 = yes, ss11 = yes, ss06 = yes, ss09 = yes,
}
-local default = {
+local default = { -- we need to merge the typescript definition in here
basics, analysis, regular, positioning, -- xxxx = yes, yyyy = 2,
}
@@ -75,7 +77,7 @@ return {
solutions = { -- here we have references to featuresets, so we use strings!
experimental = {
less = {
- "shrink"
+ "shrink", -- we need an extra one
},
more = {
"minimal_stretching", "medium_stretching", "maximal_stretching", "wide_all"
diff --git a/tex/context/interface/keys-cs.xml b/tex/context/interface/keys-cs.xml
index cd95319e0..0fe7f4b4d 100644
--- a/tex/context/interface/keys-cs.xml
+++ b/tex/context/interface/keys-cs.xml
@@ -160,6 +160,7 @@
<cd:variable name='enumeration' value='vycet'/>
<cd:variable name='environment' value='prostredi'/>
<cd:variable name='even' value='sude'/>
+ <cd:variable name='export' value='export'/>
<cd:variable name='external' value='externi'/>
<cd:variable name='fact' value='fakt'/>
<cd:variable name='february' value='unor'/>
@@ -458,6 +459,7 @@
<cd:variable name='subforward' value='podvpred'/>
<cd:variable name='subject' value='tema'/>
<cd:variable name='subpage' value='podstranka'/>
+ <cd:variable name='subs' value='subs'/>
<cd:variable name='subsection' value='podsekce'/>
<cd:variable name='subsubject' value='podtema'/>
<cd:variable name='subsubsection' value='podpodsekce'/>
@@ -690,6 +692,7 @@
<cd:constant name='filtercommand' value='filtercommand'/>
<cd:constant name='finalnamesep' value='finalnamesep'/>
<cd:constant name='firstnamesep' value='firstnamesep'/>
+ <cd:constant name='firstpage' value='prvnistranka'/>
<cd:constant name='focus' value='zaostreni'/>
<cd:constant name='focusin' value='focusin'/>
<cd:constant name='focusout' value='focusout'/>
@@ -756,6 +759,7 @@
<cd:constant name='label' value='popisek'/>
<cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
+ <cd:constant name='lastpage' value='poslednistrana'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
<cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='vlevo'/>
@@ -776,6 +780,7 @@
<cd:constant name='leftsubsentence' value='podvetavlevo'/>
<cd:constant name='lefttext' value='textvlevo'/>
<cd:constant name='leftwidth' value='sirkavlevo'/>
+ <cd:constant name='less' value='less'/>
<cd:constant name='level' value='uroven'/>
<cd:constant name='levels' value='urovne'/>
<cd:constant name='limittext' value='limittext'/>
@@ -814,6 +819,7 @@
<cd:constant name='minheight' value='minvyska'/>
<cd:constant name='minwidth' value='minsirka'/>
<cd:constant name='monthconversion' value='monthconversion'/>
+ <cd:constant name='more' value='more'/>
<cd:constant name='n' value='n'/>
<cd:constant name='name' value='jmeno'/>
<cd:constant name='namesep' value='namesep'/>
@@ -968,6 +974,7 @@
<cd:constant name='separator' value='oddelovac'/>
<cd:constant name='set' value='set'/>
<cd:constant name='setups' value='setups'/>
+ <cd:constant name='shrink' value='shrink'/>
<cd:constant name='side' value='pocitat'/>
<cd:constant name='sidealign' value='sidealign'/>
<cd:constant name='sidemethod' value='sidemethod'/>
@@ -976,6 +983,7 @@
<cd:constant name='sign' value='znak'/>
<cd:constant name='size' value='velikost'/>
<cd:constant name='small' value='male'/>
+ <cd:constant name='solution' value='solution'/>
<cd:constant name='sort' value='sort'/>
<cd:constant name='sorttype' value='sorttype'/>
<cd:constant name='source' value='zdroj'/>
diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml
index a28d23bcf..c14f7c526 100644
--- a/tex/context/interface/keys-de.xml
+++ b/tex/context/interface/keys-de.xml
@@ -160,6 +160,7 @@
<cd:variable name='enumeration' value='nummerierung'/>
<cd:variable name='environment' value='umgebung'/>
<cd:variable name='even' value='gerade'/>
+ <cd:variable name='export' value='export'/>
<cd:variable name='external' value='extern'/>
<cd:variable name='fact' value='gegeben'/>
<cd:variable name='february' value='februar'/>
@@ -458,6 +459,7 @@
<cd:variable name='subforward' value='untervorwaerts'/>
<cd:variable name='subject' value='thema'/>
<cd:variable name='subpage' value='unterseite'/>
+ <cd:variable name='subs' value='subs'/>
<cd:variable name='subsection' value='unterabsatz'/>
<cd:variable name='subsubject' value='unterthema'/>
<cd:variable name='subsubsection' value='unterunterabsatz'/>
@@ -690,6 +692,7 @@
<cd:constant name='filtercommand' value='filtercommand'/>
<cd:constant name='finalnamesep' value='finalnamesep'/>
<cd:constant name='firstnamesep' value='firstnamesep'/>
+ <cd:constant name='firstpage' value='ersteseite'/>
<cd:constant name='focus' value='focus'/>
<cd:constant name='focusin' value='focusin'/>
<cd:constant name='focusout' value='focusout'/>
@@ -756,6 +759,7 @@
<cd:constant name='label' value='label'/>
<cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
+ <cd:constant name='lastpage' value='letzteseite'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
<cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='links'/>
@@ -776,6 +780,7 @@
<cd:constant name='leftsubsentence' value='linkersubsatz'/>
<cd:constant name='lefttext' value='linkertext'/>
<cd:constant name='leftwidth' value='linkerbreite'/>
+ <cd:constant name='less' value='less'/>
<cd:constant name='level' value='niveau'/>
<cd:constant name='levels' value='niveaus'/>
<cd:constant name='limittext' value='limittext'/>
@@ -814,6 +819,7 @@
<cd:constant name='minheight' value='minhoehe'/>
<cd:constant name='minwidth' value='minbreite'/>
<cd:constant name='monthconversion' value='monthconversion'/>
+ <cd:constant name='more' value='more'/>
<cd:constant name='n' value='n'/>
<cd:constant name='name' value='name'/>
<cd:constant name='namesep' value='namesep'/>
@@ -968,6 +974,7 @@
<cd:constant name='separator' value='seperator'/>
<cd:constant name='set' value='set'/>
<cd:constant name='setups' value='setups'/>
+ <cd:constant name='shrink' value='shrink'/>
<cd:constant name='side' value='objektabstand'/>
<cd:constant name='sidealign' value='sidealign'/>
<cd:constant name='sidemethod' value='sidemethod'/>
@@ -976,6 +983,7 @@
<cd:constant name='sign' value='zeichen'/>
<cd:constant name='size' value='groesse'/>
<cd:constant name='small' value='klein'/>
+ <cd:constant name='solution' value='solution'/>
<cd:constant name='sort' value='sort'/>
<cd:constant name='sorttype' value='sorttype'/>
<cd:constant name='source' value='quelle'/>
diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml
index 80ff3c2e1..d981143b0 100644
--- a/tex/context/interface/keys-en.xml
+++ b/tex/context/interface/keys-en.xml
@@ -160,6 +160,7 @@
<cd:variable name='enumeration' value='enumeration'/>
<cd:variable name='environment' value='environment'/>
<cd:variable name='even' value='even'/>
+ <cd:variable name='export' value='export'/>
<cd:variable name='external' value='external'/>
<cd:variable name='fact' value='fact'/>
<cd:variable name='february' value='february'/>
@@ -458,6 +459,7 @@
<cd:variable name='subforward' value='subforward'/>
<cd:variable name='subject' value='subject'/>
<cd:variable name='subpage' value='subpage'/>
+ <cd:variable name='subs' value='subs'/>
<cd:variable name='subsection' value='subsection'/>
<cd:variable name='subsubject' value='subsubject'/>
<cd:variable name='subsubsection' value='subsubsection'/>
@@ -690,6 +692,7 @@
<cd:constant name='filtercommand' value='filtercommand'/>
<cd:constant name='finalnamesep' value='finalnamesep'/>
<cd:constant name='firstnamesep' value='firstnamesep'/>
+ <cd:constant name='firstpage' value='firstpage'/>
<cd:constant name='focus' value='focus'/>
<cd:constant name='focusin' value='focusin'/>
<cd:constant name='focusout' value='focusout'/>
@@ -756,6 +759,7 @@
<cd:constant name='label' value='label'/>
<cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
+ <cd:constant name='lastpage' value='lastpage'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
<cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='left'/>
@@ -776,6 +780,7 @@
<cd:constant name='leftsubsentence' value='leftsubsentence'/>
<cd:constant name='lefttext' value='lefttext'/>
<cd:constant name='leftwidth' value='leftwidth'/>
+ <cd:constant name='less' value='less'/>
<cd:constant name='level' value='level'/>
<cd:constant name='levels' value='levels'/>
<cd:constant name='limittext' value='limittext'/>
@@ -814,6 +819,7 @@
<cd:constant name='minheight' value='minheight'/>
<cd:constant name='minwidth' value='minwidth'/>
<cd:constant name='monthconversion' value='monthconversion'/>
+ <cd:constant name='more' value='more'/>
<cd:constant name='n' value='n'/>
<cd:constant name='name' value='name'/>
<cd:constant name='namesep' value='namesep'/>
@@ -968,6 +974,7 @@
<cd:constant name='separator' value='separator'/>
<cd:constant name='set' value='set'/>
<cd:constant name='setups' value='setups'/>
+ <cd:constant name='shrink' value='shrink'/>
<cd:constant name='side' value='side'/>
<cd:constant name='sidealign' value='sidealign'/>
<cd:constant name='sidemethod' value='sidemethod'/>
@@ -976,6 +983,7 @@
<cd:constant name='sign' value='sign'/>
<cd:constant name='size' value='size'/>
<cd:constant name='small' value='small'/>
+ <cd:constant name='solution' value='solution'/>
<cd:constant name='sort' value='sort'/>
<cd:constant name='sorttype' value='sorttype'/>
<cd:constant name='source' value='source'/>
diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml
index d97bf932a..3d25240bf 100644
--- a/tex/context/interface/keys-fr.xml
+++ b/tex/context/interface/keys-fr.xml
@@ -160,6 +160,7 @@
<cd:variable name='enumeration' value='enumeration'/>
<cd:variable name='environment' value='environement'/>
<cd:variable name='even' value='paire'/>
+ <cd:variable name='export' value='export'/>
<cd:variable name='external' value='external'/>
<cd:variable name='fact' value='fait'/>
<cd:variable name='february' value='fevrier'/>
@@ -458,6 +459,7 @@
<cd:variable name='subforward' value='sousavance'/>
<cd:variable name='subject' value='sujet'/>
<cd:variable name='subpage' value='souspage'/>
+ <cd:variable name='subs' value='subs'/>
<cd:variable name='subsection' value='soussection'/>
<cd:variable name='subsubject' value='soussujet'/>
<cd:variable name='subsubsection' value='soussoussection'/>
@@ -690,6 +692,7 @@
<cd:constant name='filtercommand' value='filtercommand'/>
<cd:constant name='finalnamesep' value='finalnamesep'/>
<cd:constant name='firstnamesep' value='firstnamesep'/>
+ <cd:constant name='firstpage' value='premierepage'/>
<cd:constant name='focus' value='focus'/>
<cd:constant name='focusin' value='focusin'/>
<cd:constant name='focusout' value='focusout'/>
@@ -756,6 +759,7 @@
<cd:constant name='label' value='etiquette'/>
<cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
+ <cd:constant name='lastpage' value='dernierepage'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
<cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='gauche'/>
@@ -776,6 +780,7 @@
<cd:constant name='leftsubsentence' value='sousphrasegauche'/>
<cd:constant name='lefttext' value='textegauche'/>
<cd:constant name='leftwidth' value='largeurgauche'/>
+ <cd:constant name='less' value='less'/>
<cd:constant name='level' value='niveau'/>
<cd:constant name='levels' value='niveaux'/>
<cd:constant name='limittext' value='limittext'/>
@@ -814,6 +819,7 @@
<cd:constant name='minheight' value='hauteurmin'/>
<cd:constant name='minwidth' value='largeurmin'/>
<cd:constant name='monthconversion' value='monthconversion'/>
+ <cd:constant name='more' value='more'/>
<cd:constant name='n' value='n'/>
<cd:constant name='name' value='nom'/>
<cd:constant name='namesep' value='namesep'/>
@@ -968,6 +974,7 @@
<cd:constant name='separator' value='separateur'/>
<cd:constant name='set' value='set'/>
<cd:constant name='setups' value='reglages'/>
+ <cd:constant name='shrink' value='shrink'/>
<cd:constant name='side' value='cote'/>
<cd:constant name='sidealign' value='sidealign'/>
<cd:constant name='sidemethod' value='sidemethod'/>
@@ -976,6 +983,7 @@
<cd:constant name='sign' value='signe'/>
<cd:constant name='size' value='dimension'/>
<cd:constant name='small' value='petit'/>
+ <cd:constant name='solution' value='solution'/>
<cd:constant name='sort' value='sort'/>
<cd:constant name='sorttype' value='sorttype'/>
<cd:constant name='source' value='origine'/>
diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml
index a03a88ba3..cc08f1e3e 100644
--- a/tex/context/interface/keys-it.xml
+++ b/tex/context/interface/keys-it.xml
@@ -160,6 +160,7 @@
<cd:variable name='enumeration' value='enumerazione'/>
<cd:variable name='environment' value='ambiente'/>
<cd:variable name='even' value='pari'/>
+ <cd:variable name='export' value='export'/>
<cd:variable name='external' value='esterno'/>
<cd:variable name='fact' value='fatto'/>
<cd:variable name='february' value='febbraio'/>
@@ -458,6 +459,7 @@
<cd:variable name='subforward' value='sottoavanti'/>
<cd:variable name='subject' value='argomento'/>
<cd:variable name='subpage' value='sottopagina'/>
+ <cd:variable name='subs' value='subs'/>
<cd:variable name='subsection' value='sottocapoverso'/>
<cd:variable name='subsubject' value='sottoargomento'/>
<cd:variable name='subsubsection' value='sottosottocapoverso'/>
@@ -690,6 +692,7 @@
<cd:constant name='filtercommand' value='filtercommand'/>
<cd:constant name='finalnamesep' value='finalnamesep'/>
<cd:constant name='firstnamesep' value='firstnamesep'/>
+ <cd:constant name='firstpage' value='primapagina'/>
<cd:constant name='focus' value='focus'/>
<cd:constant name='focusin' value='focusin'/>
<cd:constant name='focusout' value='focusout'/>
@@ -756,6 +759,7 @@
<cd:constant name='label' value='etichetta'/>
<cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
+ <cd:constant name='lastpage' value='ultimapagina'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
<cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='sinistra'/>
@@ -776,6 +780,7 @@
<cd:constant name='leftsubsentence' value='sottofrasesinistra'/>
<cd:constant name='lefttext' value='testosinistro'/>
<cd:constant name='leftwidth' value='ampiezzasinistra'/>
+ <cd:constant name='less' value='less'/>
<cd:constant name='level' value='livello'/>
<cd:constant name='levels' value='livelli'/>
<cd:constant name='limittext' value='limittext'/>
@@ -814,6 +819,7 @@
<cd:constant name='minheight' value='altezzamin'/>
<cd:constant name='minwidth' value='ampiezzamin'/>
<cd:constant name='monthconversion' value='monthconversion'/>
+ <cd:constant name='more' value='more'/>
<cd:constant name='n' value='n'/>
<cd:constant name='name' value='nome'/>
<cd:constant name='namesep' value='namesep'/>
@@ -968,6 +974,7 @@
<cd:constant name='separator' value='separatore'/>
<cd:constant name='set' value='set'/>
<cd:constant name='setups' value='setups'/>
+ <cd:constant name='shrink' value='shrink'/>
<cd:constant name='side' value='lato'/>
<cd:constant name='sidealign' value='sidealign'/>
<cd:constant name='sidemethod' value='sidemethod'/>
@@ -976,6 +983,7 @@
<cd:constant name='sign' value='segno'/>
<cd:constant name='size' value='dimensione'/>
<cd:constant name='small' value='piccolo'/>
+ <cd:constant name='solution' value='solution'/>
<cd:constant name='sort' value='sort'/>
<cd:constant name='sorttype' value='sorttype'/>
<cd:constant name='source' value='origine'/>
diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml
index 2c9113c39..039d6e882 100644
--- a/tex/context/interface/keys-nl.xml
+++ b/tex/context/interface/keys-nl.xml
@@ -160,6 +160,7 @@
<cd:variable name='enumeration' value='doornummering'/>
<cd:variable name='environment' value='omgeving'/>
<cd:variable name='even' value='even'/>
+ <cd:variable name='export' value='export'/>
<cd:variable name='external' value='extern'/>
<cd:variable name='fact' value='gegeven'/>
<cd:variable name='february' value='februari'/>
@@ -458,6 +459,7 @@
<cd:variable name='subforward' value='subvooruit'/>
<cd:variable name='subject' value='onderwerp'/>
<cd:variable name='subpage' value='subpagina'/>
+ <cd:variable name='subs' value='subs'/>
<cd:variable name='subsection' value='subparagraaf'/>
<cd:variable name='subsubject' value='subonderwerp'/>
<cd:variable name='subsubsection' value='subsubparagraaf'/>
@@ -690,6 +692,7 @@
<cd:constant name='filtercommand' value='filtercommand'/>
<cd:constant name='finalnamesep' value='finalnamesep'/>
<cd:constant name='firstnamesep' value='firstnamesep'/>
+ <cd:constant name='firstpage' value='eerstepagina'/>
<cd:constant name='focus' value='focus'/>
<cd:constant name='focusin' value='focusin'/>
<cd:constant name='focusout' value='focusuit'/>
@@ -756,6 +759,7 @@
<cd:constant name='label' value='label'/>
<cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
+ <cd:constant name='lastpage' value='laatstepagina'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
<cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='links'/>
@@ -776,6 +780,7 @@
<cd:constant name='leftsubsentence' value='linkersubzin'/>
<cd:constant name='lefttext' value='linkertekst'/>
<cd:constant name='leftwidth' value='linkerbreedte'/>
+ <cd:constant name='less' value='minder'/>
<cd:constant name='level' value='niveau'/>
<cd:constant name='levels' value='niveaus'/>
<cd:constant name='limittext' value='limiettekst'/>
@@ -814,6 +819,7 @@
<cd:constant name='minheight' value='minhoogte'/>
<cd:constant name='minwidth' value='minbreedte'/>
<cd:constant name='monthconversion' value='maandconversie'/>
+ <cd:constant name='more' value='meer'/>
<cd:constant name='n' value='n'/>
<cd:constant name='name' value='naam'/>
<cd:constant name='namesep' value='namesep'/>
@@ -968,6 +974,7 @@
<cd:constant name='separator' value='scheider'/>
<cd:constant name='set' value='set'/>
<cd:constant name='setups' value='setups'/>
+ <cd:constant name='shrink' value='krimp'/>
<cd:constant name='side' value='zij'/>
<cd:constant name='sidealign' value='zijuitlijnen'/>
<cd:constant name='sidemethod' value='zijmethode'/>
@@ -976,6 +983,7 @@
<cd:constant name='sign' value='teken'/>
<cd:constant name='size' value='formaat'/>
<cd:constant name='small' value='klein'/>
+ <cd:constant name='solution' value='oplossing'/>
<cd:constant name='sort' value='sort'/>
<cd:constant name='sorttype' value='sortering'/>
<cd:constant name='source' value='bron'/>
diff --git a/tex/context/interface/keys-pe.xml b/tex/context/interface/keys-pe.xml
index 5f48acdd0..6615a3488 100644
--- a/tex/context/interface/keys-pe.xml
+++ b/tex/context/interface/keys-pe.xml
@@ -160,6 +160,7 @@
<cd:variable name='enumeration' value='شماره‌بندی'/>
<cd:variable name='environment' value='محیط'/>
<cd:variable name='even' value='زوج'/>
+ <cd:variable name='export' value='export'/>
<cd:variable name='external' value='خارجی'/>
<cd:variable name='fact' value='fact'/>
<cd:variable name='february' value='فوریه'/>
@@ -458,6 +459,7 @@
<cd:variable name='subforward' value='زیرجلوگرد'/>
<cd:variable name='subject' value='موضوع'/>
<cd:variable name='subpage' value='زیرصفحه'/>
+ <cd:variable name='subs' value='subs'/>
<cd:variable name='subsection' value='زیربخش'/>
<cd:variable name='subsubject' value='زیرموضوع'/>
<cd:variable name='subsubsection' value='زیرزیربخش'/>
@@ -690,6 +692,7 @@
<cd:constant name='filtercommand' value='filtercommand'/>
<cd:constant name='finalnamesep' value='finalnamesep'/>
<cd:constant name='firstnamesep' value='firstnamesep'/>
+ <cd:constant name='firstpage' value='صفحه‌اول'/>
<cd:constant name='focus' value='تمرکز'/>
<cd:constant name='focusin' value='تمرکزدرون'/>
<cd:constant name='focusout' value='تمرکزبیرون'/>
@@ -756,6 +759,7 @@
<cd:constant name='label' value='برچسب'/>
<cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
+ <cd:constant name='lastpage' value='صفحه‌آخر'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
<cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='چپ'/>
@@ -776,6 +780,7 @@
<cd:constant name='leftsubsentence' value='زیرجمله‌چپ'/>
<cd:constant name='lefttext' value='متن‌چپ'/>
<cd:constant name='leftwidth' value='عرض‌خط'/>
+ <cd:constant name='less' value='less'/>
<cd:constant name='level' value='مرحله'/>
<cd:constant name='levels' value='مرحله‌ها'/>
<cd:constant name='limittext' value='مرزمتن'/>
@@ -814,6 +819,7 @@
<cd:constant name='minheight' value='کمترین‌ارتفاع'/>
<cd:constant name='minwidth' value='کمترین‌عرض'/>
<cd:constant name='monthconversion' value='monthconversion'/>
+ <cd:constant name='more' value='more'/>
<cd:constant name='n' value='n'/>
<cd:constant name='name' value='نام'/>
<cd:constant name='namesep' value='namesep'/>
@@ -968,6 +974,7 @@
<cd:constant name='separator' value='جداکننده'/>
<cd:constant name='set' value='قراربده'/>
<cd:constant name='setups' value='بارگذاریها'/>
+ <cd:constant name='shrink' value='shrink'/>
<cd:constant name='side' value='کنار'/>
<cd:constant name='sidealign' value='تنظیم‌کنار'/>
<cd:constant name='sidemethod' value='روش‌کنار'/>
@@ -976,6 +983,7 @@
<cd:constant name='sign' value='علامت'/>
<cd:constant name='size' value='اندازه'/>
<cd:constant name='small' value='کوچک'/>
+ <cd:constant name='solution' value='solution'/>
<cd:constant name='sort' value='sort'/>
<cd:constant name='sorttype' value='ترتیب‌تایپ'/>
<cd:constant name='source' value='منبع'/>
diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml
index 22ccf09c0..fb827945e 100644
--- a/tex/context/interface/keys-ro.xml
+++ b/tex/context/interface/keys-ro.xml
@@ -160,6 +160,7 @@
<cd:variable name='enumeration' value='enumerare'/>
<cd:variable name='environment' value='mediu'/>
<cd:variable name='even' value='par'/>
+ <cd:variable name='export' value='export'/>
<cd:variable name='external' value='extern'/>
<cd:variable name='fact' value='fapt'/>
<cd:variable name='february' value='februarie'/>
@@ -458,6 +459,7 @@
<cd:variable name='subforward' value='subavans'/>
<cd:variable name='subject' value='subiect'/>
<cd:variable name='subpage' value='subpagina'/>
+ <cd:variable name='subs' value='subs'/>
<cd:variable name='subsection' value='subsectiune'/>
<cd:variable name='subsubject' value='subsubiect'/>
<cd:variable name='subsubsection' value='subsubsectiune'/>
@@ -690,6 +692,7 @@
<cd:constant name='filtercommand' value='filtercommand'/>
<cd:constant name='finalnamesep' value='finalnamesep'/>
<cd:constant name='firstnamesep' value='firstnamesep'/>
+ <cd:constant name='firstpage' value='primapagina'/>
<cd:constant name='focus' value='focus'/>
<cd:constant name='focusin' value='focusin'/>
<cd:constant name='focusout' value='focusout'/>
@@ -756,6 +759,7 @@
<cd:constant name='label' value='eticheta'/>
<cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
+ <cd:constant name='lastpage' value='ultimapagina'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
<cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='stanga'/>
@@ -776,6 +780,7 @@
<cd:constant name='leftsubsentence' value='subpropozitiestanga'/>
<cd:constant name='lefttext' value='textstanga'/>
<cd:constant name='leftwidth' value='latimestanga'/>
+ <cd:constant name='less' value='less'/>
<cd:constant name='level' value='nivel'/>
<cd:constant name='levels' value='nivele'/>
<cd:constant name='limittext' value='limittext'/>
@@ -814,6 +819,7 @@
<cd:constant name='minheight' value='inaltimeminima'/>
<cd:constant name='minwidth' value='latimeminima'/>
<cd:constant name='monthconversion' value='monthconversion'/>
+ <cd:constant name='more' value='more'/>
<cd:constant name='n' value='n'/>
<cd:constant name='name' value='nume'/>
<cd:constant name='namesep' value='namesep'/>
@@ -968,6 +974,7 @@
<cd:constant name='separator' value='separator'/>
<cd:constant name='set' value='set'/>
<cd:constant name='setups' value='setups'/>
+ <cd:constant name='shrink' value='shrink'/>
<cd:constant name='side' value='parte'/>
<cd:constant name='sidealign' value='sidealign'/>
<cd:constant name='sidemethod' value='sidemethod'/>
@@ -976,6 +983,7 @@
<cd:constant name='sign' value='semn'/>
<cd:constant name='size' value='dimensiune'/>
<cd:constant name='small' value='mic'/>
+ <cd:constant name='solution' value='solution'/>
<cd:constant name='sort' value='sort'/>
<cd:constant name='sorttype' value='sorttype'/>
<cd:constant name='source' value='sursa'/>
diff --git a/tex/context/sample/lorem.tex b/tex/context/sample/lorem.tex
new file mode 100644
index 000000000..0132f659f
--- /dev/null
+++ b/tex/context/sample/lorem.tex
@@ -0,0 +1,11 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur massa turpis,
+semper quis fringilla ut, viverra nec risus. Pellentesque habitant morbi
+tristique senectus et netus et malesuada fames ac turpis egestas. Donec nunc
+lorem, sollicitudin vel sodales eget, vehicula nec mi. Proin ullamcorper rutrum
+nibh, at porttitor nunc euismod et. Donec faucibus nisi faucibus ipsum porttitor
+pharetra. Sed elementum, lectus nec congue imperdiet, ipsum leo viverra nisi, sit
+amet commodo odio odio id nisl. Fusce sagittis lobortis nisi sed consectetur. Nam
+egestas, sem ut fermentum convallis, ipsum tellus venenatis augue, eget
+condimentum risus quam id erat. Sed metus dui, sollicitudin pharetra pellentesque
+sed, placerat eget augue. Mauris sodales pretium tortor vitae rutrum. Proin quam
+sem, lobortis tincidunt pretium vitae, feugiat eu lacus.
diff --git a/tex/context/test/pdf-x1a-2001.mkiv b/tex/context/test/pdf-x1a-2001.mkiv
index a304c8963..f1c5ef531 100644
--- a/tex/context/test/pdf-x1a-2001.mkiv
+++ b/tex/context/test/pdf-x1a-2001.mkiv
@@ -1,6 +1,6 @@
% PDF/X-1a:2001
-\enabletrackers[backend.pdfx]
+\enabletrackers[backend.format,backend.variables]
\setupbackend
[format=PDF/X-1a:2001,
diff --git a/tex/context/test/pdf-x1a-2003.mkiv b/tex/context/test/pdf-x1a-2003.mkiv
index 89a0f6066..7fbec5acb 100644
--- a/tex/context/test/pdf-x1a-2003.mkiv
+++ b/tex/context/test/pdf-x1a-2003.mkiv
@@ -1,6 +1,6 @@
% PDF/X-1a:2003
-\enabletrackers[backend.pdfx]
+\enabletrackers[backend.format,backend.variables]
\setupbackend
[format=PDF/X-1a:2003,
diff --git a/tex/context/test/pdf-x3-2002.mkiv b/tex/context/test/pdf-x3-2002.mkiv
index 1e2310135..be757212e 100644
--- a/tex/context/test/pdf-x3-2002.mkiv
+++ b/tex/context/test/pdf-x3-2002.mkiv
@@ -1,6 +1,6 @@
% PDF/X-3:2002
-\enabletrackers[backend.pdfx]
+\enabletrackers[backend.format,backend.variables]
\setupbackend
[format=PDF/X-3:2002,
diff --git a/tex/context/test/pdf-x3-2003.mkiv b/tex/context/test/pdf-x3-2003.mkiv
index bedcde527..cbebe1033 100644
--- a/tex/context/test/pdf-x3-2003.mkiv
+++ b/tex/context/test/pdf-x3-2003.mkiv
@@ -1,6 +1,6 @@
% PDF/X-3:2003
-\enabletrackers[backend.pdfx]
+\enabletrackers[backend.format,backend.variables]
\setupbackend
[format=PDF/X-3:2003,
diff --git a/tex/context/test/pdf-x4.mkiv b/tex/context/test/pdf-x4.mkiv
index 0566475b5..062de3b34 100644
--- a/tex/context/test/pdf-x4.mkiv
+++ b/tex/context/test/pdf-x4.mkiv
@@ -2,7 +2,7 @@
% \nopdfcompression
-\enabletrackers[backend.pdfx]
+\enabletrackers[backend.format,backend.variables]
\setupbackend
[format=PDF/X-4,
diff --git a/tex/context/test/pdf-x4p.mkiv b/tex/context/test/pdf-x4p.mkiv
index 9ec8897f8..bfee0b238 100644
--- a/tex/context/test/pdf-x4p.mkiv
+++ b/tex/context/test/pdf-x4p.mkiv
@@ -1,10 +1,10 @@
% PDF/X-4p
-\enabletrackers[backend.pdfx]
+\enabletrackers[backend.format,backend.variables]
\setupbackend
[format=PDF/X-4p,
- intent=ISOcoated_v2_eci.icc,
+ intent={ISO Coated v2 (ECI)},
profile=sRGB.icc] % test for default colorspace
\input pdf-x-common.mkiv
diff --git a/tex/generic/context/luatex/luatex-basics-gen.lua b/tex/generic/context/luatex/luatex-basics-gen.lua
index bdbc3cf51..2f03efba8 100644
--- a/tex/generic/context/luatex/luatex-basics-gen.lua
+++ b/tex/generic/context/luatex/luatex-basics-gen.lua
@@ -87,7 +87,7 @@ local remapper = {
function resolvers.findfile(name,fileformat)
name = string.gsub(name,"\\","\/")
fileformat = fileformat and string.lower(fileformat)
- local found = kpse.find_file(name,(fileformat and fileformat ~= "" and (remapper[fileformat] or fileformat)) or file.extname(name,"tex"))
+ local found = kpse.find_file(name,(fileformat and fileformat ~= "" and (remapper[fileformat] or fileformat)) or file.suffix(name,"tex"))
if not found or found == "" then
found = kpse.find_file(name,"other text files")
end
@@ -96,7 +96,7 @@ end
function resolvers.findbinfile(name,fileformat)
if not fileformat or fileformat == "" then
- fileformat = file.extname(name) -- string.match(name,"%.([^%.]-)$")
+ fileformat = file.suffix(name) -- string.match(name,"%.([^%.]-)$")
end
return resolvers.findfile(name,(fileformat and remapper[fileformat]) or fileformat)
end
diff --git a/tex/generic/context/luatex/luatex-fonts-ext.lua b/tex/generic/context/luatex/luatex-fonts-ext.lua
index d8884ccc7..b60d04512 100644
--- a/tex/generic/context/luatex/luatex-fonts-ext.lua
+++ b/tex/generic/context/luatex/luatex-fonts-ext.lua
@@ -18,18 +18,14 @@ local otffeatures = fonts.constructors.newfeatures("otf")
local function initializeitlc(tfmdata,value)
if value then
- -- the magic 40 and it formula come from Dohyun Kim
- local parameters = tfmdata.parameters
+ -- 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.hasitalics = 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
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index ea509c338..777defd88 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 05/30/12 11:26:34
+-- merge date : 10/19/12 00:06:05
do -- begin closure to overcome local limits and interference
@@ -118,11 +118,28 @@ function string.topattern(str,lowercase,strict)
end
end
+
+function string.valid(str,default)
+ return (type(str) == "string" and str ~= "" and str) or default or nil
+end
+
-- obsolete names:
string.quote = string.quoted
string.unquote = string.unquoted
+-- handy fallback
+
+string.itself = function(s) return s end
+
+-- also handy (see utf variant)
+
+local pattern = Ct(C(1)^0)
+
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+
end -- closure
do -- begin closure to overcome local limits and interference
@@ -135,7 +152,8 @@ if not modules then modules = { } end modules ['l-table'] = {
license = "see context related readme files"
}
-local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string
+local type, next, tostring, tonumber, ipairs = type, next, tostring, tonumber, ipairs
+local table, string = table, string
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
@@ -146,6 +164,8 @@ local getinfo = debug.getinfo
-- impact on ConTeXt was not that large; the remaining ipairs already
-- have been replaced. In a similar fashion we also hardly used pairs.
--
+-- Hm, actually ipairs was retained, but we no longer use it anyway.
+--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -205,12 +225,16 @@ function table.strip(tab)
end
function table.keys(t)
- local keys, k = { }, 0
- for key, _ in next, t do
- k = k + 1
- keys[k] = key
+ if t then
+ local keys, k = { }, 0
+ for key, _ in next, t do
+ k = k + 1
+ keys[k] = key
+ end
+ return keys
+ else
+ return { }
end
- return keys
end
local function compare(a,b)
@@ -223,41 +247,49 @@ local function compare(a,b)
end
local function sortedkeys(tab)
- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
- for key,_ in next, tab do
- s = s + 1
- srt[s] = key
- if category == 3 then
- -- no further check
- else
- local tkey = type(key)
- if tkey == "string" then
- category = (category == 2 and 3) or 1
- elseif tkey == "number" then
- category = (category == 1 and 3) or 2
+ if tab then
+ local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ for key,_ in next, tab do
+ s = s + 1
+ srt[s] = key
+ if category == 3 then
+ -- no further check
else
- category = 3
+ local tkey = type(key)
+ if tkey == "string" then
+ category = (category == 2 and 3) or 1
+ elseif tkey == "number" then
+ category = (category == 1 and 3) or 2
+ else
+ category = 3
+ end
end
end
- end
- if category == 0 or category == 3 then
- sort(srt,compare)
+ if category == 0 or category == 3 then
+ sort(srt,compare)
+ else
+ sort(srt)
+ end
+ return srt
else
- sort(srt)
+ return { }
end
- return srt
end
local function sortedhashkeys(tab) -- fast one
- local srt, s = { }, 0
- for key,_ in next, tab do
- if key then
- s= s + 1
- srt[s] = key
+ if tab then
+ local srt, s = { }, 0
+ for key,_ in next, tab do
+ if key then
+ s= s + 1
+ srt[s] = key
+ end
end
+ sort(srt)
+ return srt
+ else
+ return { }
end
- sort(srt)
- return srt
end
table.sortedkeys = sortedkeys
@@ -282,7 +314,7 @@ end
table.sortedhash = sortedhash
table.sortedpairs = sortedhash
-function table.append(t, list)
+function table.append(t,list)
local n = #t
for i=1,#list do
n = n + 1
@@ -517,12 +549,26 @@ local function do_serialize(root,name,depth,level,indexed)
end
-- we could check for k (index) being number (cardinal)
if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
+ -- if compact then
+ -- -- NOT: for k=1,#root do (we need to quit at nil)
+ -- for k,v in ipairs(root) do -- can we use next?
+ -- if not first then first = k end
+ -- last = last + 1
+ -- end
+ -- end
+ local first, last = nil, 0
if compact then
- -- NOT: for k=1,#root do (we need to quit at nil)
- for k,v in ipairs(root) do -- can we use next?
- if not first then first = k end
- last = last + 1
+ last = #root
+ for k=1,last do
+-- if not root[k] then
+ if root[k] == nil then
+ last = k - 1
+ break
+ end
+ end
+ if last > 0 then
+ first = 1
end
end
local sk = sortedkeys(root)
@@ -1014,23 +1060,27 @@ function table.reversed(t)
end
end
-function table.sequenced(t,sep,simple) -- hash only
- local s, n = { }, 0
- for k, v in sortedhash(t) do
- if simple then
- if v == true then
- n = n + 1
- s[n] = k
- elseif v and v~= "" then
+function table.sequenced(t,sep) -- hash only
+ if t then
+ local s, n = { }, 0
+ for k, v in sortedhash(t) do
+ if simple then
+ if v == true then
+ n = n + 1
+ s[n] = k
+ elseif v and v~= "" then
+ n = n + 1
+ s[n] = k .. "=" .. tostring(v)
+ end
+ else
n = n + 1
s[n] = k .. "=" .. tostring(v)
end
- else
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
end
+ return concat(s, sep or " | ")
+ else
+ return ""
end
- return concat(s, sep or " | ")
end
function table.print(t,...)
@@ -1110,6 +1160,8 @@ local lpeg = require("lpeg")
-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+-- some code will move to unicode and string
+
local report = texio and texio.write_nl or print
-- local lpmatch = lpeg.match
@@ -1146,8 +1198,8 @@ local report = texio and texio.write_nl or print
-- 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
+local type, next = type, next
+local byte, char, gmatch, format = string.byte, string.char, string.gmatch, string.format
-- 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.
@@ -1155,9 +1207,8 @@ local byte, char, gmatch = string.byte, string.char, string.gmatch
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 P, R, S, V, Ct, C, Cs, Cc, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Cp
+local lpegtype, lpegmatch = lpeg.type, lpeg.match
local utfcharacters = string.utfcharacters
local utfgmatch = unicode and unicode.utf8.gmatch
@@ -1208,6 +1259,10 @@ patterns.utf8char = utf8char
patterns.validutf8 = validutf8char
patterns.validutf8char = validutf8char
+local eol = S("\n\r")
+local spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+local whitespace = eol + spacer
+
patterns.digit = digit
patterns.sign = sign
patterns.cardinal = sign^0 * digit^1
@@ -1227,16 +1282,16 @@ 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.eol = eol
+patterns.spacer = spacer
+patterns.whitespace = whitespace
patterns.newline = newline
patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.nonspacer = 1 - spacer
+patterns.nonwhitespace = 1 - whitespace
patterns.equal = P("=")
patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.commaspacer = P(",") * spacer^0
patterns.period = P(".")
patterns.colon = P(":")
patterns.semicolon = P(";")
@@ -1251,6 +1306,10 @@ patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
patterns.unspacer = ((patterns.spacer^1)/"")^0
+patterns.singlequoted = squote * patterns.nosquote * squote
+patterns.doublequoted = dquote * patterns.nodquote * dquote
+patterns.quoted = patterns.doublequoted + patterns.singlequoted
+
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
@@ -1261,8 +1320,17 @@ patterns.beginline = #(1-newline)
-- 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?
+local function anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) }
+end
+
+lpeg.anywhere = anywhere
+
+function lpeg.instringchecker(p)
+ p = anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
end
function lpeg.splitter(pattern, action)
@@ -1311,13 +1379,13 @@ function string.splitup(str,separator)
if not separator then
separator = ","
end
- return match(splitters_m[separator] or splitat(separator),str)
+ return lpegmatch(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 p = splitat("->",false) print(lpegmatch(p,"oeps->what->more")) -- oeps what more
+--~ local p = splitat("->",true) print(lpegmatch(p,"oeps->what->more")) -- oeps what->more
+--~ local p = splitat("->",false) print(lpegmatch(p,"oeps")) -- oeps
+--~ local p = splitat("->",true) print(lpegmatch(p,"oeps")) -- oeps
local cache = { }
@@ -1327,16 +1395,20 @@ function lpeg.split(separator,str)
c = tsplitat(separator)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
+ if separator then
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
end
- return match(c,str)
end
local spacing = patterns.spacer^0 * newline -- sort of strip
@@ -1349,7 +1421,7 @@ patterns.textline = content
--~ local linesplitter = Ct(content^0)
--~
--~ function string.splitlines(str)
---~ return match(linesplitter,str)
+--~ return lpegmatch(linesplitter,str)
--~ end
local linesplitter = tsplitat(newline)
@@ -1357,7 +1429,7 @@ local linesplitter = tsplitat(newline)
patterns.linesplitter = linesplitter
function string.splitlines(str)
- return match(linesplitter,str)
+ return lpegmatch(linesplitter,str)
end
local utflinesplitter = utfbom^-1 * tsplitat(newline)
@@ -1365,7 +1437,58 @@ local utflinesplitter = utfbom^-1 * tsplitat(newline)
patterns.utflinesplitter = utflinesplitter
function string.utfsplitlines(str)
- return match(utflinesplitter,str or "")
+ return lpegmatch(utflinesplitter,str or "")
+end
+
+local utfcharsplitter_ows = utfbom^-1 * Ct(C(utf8char)^0)
+local utfcharsplitter_iws = utfbom^-1 * Ct((whitespace^1 + C(utf8char))^0)
+
+function string.utfsplit(str,ignorewhitespace) -- new
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+
+-- inspect(string.utfsplit("a b c d"))
+-- inspect(string.utfsplit("a b c d",true))
+
+-- -- alternative 1: 0.77
+--
+-- local utfcharcounter = utfbom^-1 * Cs((utf8char/'!')^0)
+--
+-- function string.utflength(str)
+-- return #lpegmatch(utfcharcounter,str or "")
+-- end
+--
+-- -- alternative 2: 1.70
+--
+-- local n = 0
+--
+-- local utfcharcounter = utfbom^-1 * (utf8char/function() n = n + 1 end)^0 -- slow
+--
+-- function string.utflength(str)
+-- n = 0
+-- lpegmatch(utfcharcounter,str or "")
+-- return n
+-- end
+--
+-- -- alternative 3: 0.24 (native unicode.utf8.len: 0.047)
+
+local n = 0
+
+local utfcharcounter = utfbom^-1 * Cs ( (
+ Cp() * (lpeg.patterns.utf8one )^1 * Cp() / function(f,t) n = n + t - f end
+ + Cp() * (lpeg.patterns.utf8two )^1 * Cp() / function(f,t) n = n + (t - f)/2 end
+ + Cp() * (lpeg.patterns.utf8three)^1 * Cp() / function(f,t) n = n + (t - f)/3 end
+ + Cp() * (lpeg.patterns.utf8four )^1 * Cp() / function(f,t) n = n + (t - f)/4 end
+)^0 )
+
+function string.utflength(str)
+ n = 0
+ lpegmatch(utfcharcounter,str or "")
+ return n
end
--~ lpeg.splitters = cache -- no longer public
@@ -1380,7 +1503,7 @@ function lpeg.checkedsplit(separator,str)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
function string.checkedsplit(str,separator)
@@ -1391,7 +1514,7 @@ function string.checkedsplit(str,separator)
c = Ct(separator^0 * other * (separator^1 * other)^0)
cache[separator] = c
end
- return match(c,str)
+ return lpegmatch(c,str)
end
--~ from roberto's site:
@@ -1406,10 +1529,10 @@ 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 s = lpeg.stripper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.stripper("ab") print("["..lpegmatch(s,str).."]")
+--~ local s = lpeg.keeper("ab") print("["..lpegmatch(s,str).."]")
local cache = { }
@@ -1442,11 +1565,11 @@ function lpeg.keeper(str)
end
function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
+ return (P(str) + P(true)) * Cs(anything^0)
end
function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
+ return Cs((1 - P(str) * endofstring)^0)
end
-- Just for fun I looked at the used bytecode and
@@ -1455,8 +1578,22 @@ end
function lpeg.replacer(one,two)
if type(one) == "table" then
local no = #one
- if no > 0 then
- local p
+ local p
+ if no == 0 then
+ for k, v in next, one do
+ local pp = P(k) / v
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ elseif no == 1 then
+ local o = one[1]
+ one, two = P(o[1]), o[2]
+ return Cs(((1-one)^1 + one/two)^0)
+ else
for i=1,no do
local o = one[i]
local pp = P(o[1]) / o[2]
@@ -1469,11 +1606,16 @@ function lpeg.replacer(one,two)
return Cs((p + 1)^0)
end
else
+ one = P(one)
two = two or ""
- return Cs((P(one)/two + 1)^0)
+ return Cs(((1-one)^1 + one/two)^0)
end
end
+-- print(lpeg.match(lpeg.replacer("e","a"),"test test"))
+-- print(lpeg.match(lpeg.replacer{{"e","a"}},"test test"))
+-- print(lpeg.match(lpeg.replacer({ e = "a", t = "x" }),"test test"))
+
local splitters_f, splitters_s = { }, { }
function lpeg.firstofsplit(separator) -- always return value
@@ -1501,14 +1643,14 @@ function lpeg.balancer(left,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"))
+--~ print(1,lpegmatch(lpeg.firstofsplit(":"),"bc:de"))
+--~ print(2,lpegmatch(lpeg.firstofsplit(":"),":de")) -- empty
+--~ print(3,lpegmatch(lpeg.firstofsplit(":"),"bc"))
+--~ print(4,lpegmatch(lpeg.secondofsplit(":"),"bc:de"))
+--~ print(5,lpegmatch(lpeg.secondofsplit(":"),"bc:")) -- empty
+--~ print(6,lpegmatch(lpeg.secondofsplit(":",""),"bc"))
+--~ print(7,lpegmatch(lpeg.secondofsplit(":"),"bc"))
+--~ print(9,lpegmatch(lpeg.secondofsplit(":","123"),"bc"))
--~ -- slower:
--~
@@ -1522,7 +1664,7 @@ local nany = utf8char/""
function lpeg.counter(pattern)
pattern = Cs((P(pattern)/" " + nany)^0)
return function(str)
- return #match(pattern,str)
+ return #lpegmatch(pattern,str)
end
end
@@ -1536,7 +1678,7 @@ if utfgmatch then
end
return n
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -1551,9 +1693,9 @@ else
p = Cs((P(what)/" " + nany)^0)
cache[p] = p
end
- return #match(p,str)
+ return #lpegmatch(p,str)
else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
+ return #lpegmatch(Cs((P(what)/" " + nany)^0),str)
end
end
@@ -1580,7 +1722,7 @@ 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)
+ return lpegmatch(simple and s or p,str)
end
-- utf extensies
@@ -1627,7 +1769,7 @@ else
p = P(uc)
end
end
- match((utf8char/f)^0,str)
+ lpegmatch((utf8char/f)^0,str)
return p
end
@@ -1643,7 +1785,7 @@ function lpeg.UR(str,more)
first = str
last = more or first
else
- first, last = match(range,str)
+ first, last = lpegmatch(range,str)
if not last then
return P(str)
end
@@ -1679,11 +1821,15 @@ end
--~ print(lpeg.count("äáàa",lpeg.UR("àá")))
--~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then") -- assume proper order
if type(list) ~= "table" then
list = { list, ... }
end
- -- sort(list) -- longest match first
+ -- table.sort(list) -- longest match first
local p = P(list[1])
for l=2,#list do
p = p + P(list[l])
@@ -1691,10 +1837,6 @@ function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
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.
@@ -1852,6 +1994,24 @@ end
-- utfchar(0x205F), -- math thinspace
-- } )
+-- handy from within tex:
+
+local lpegmatch = lpeg.match
+
+local replacer = lpeg.replacer("@","%%") -- Watch the escaped % in lpeg!
+
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+
+-- strips leading and trailing spaces and collapsed all other spaces
+
+local pattern = Cs(whitespace^0/"" * ((whitespace^1 * P(-1) / "") + (whitespace^1/" ") + P(1))^0)
+
+function string.collapsespaces(str)
+ return lpegmatch(pattern,str)
+end
+
end -- closure
do -- begin closure to overcome local limits and interference
@@ -1874,28 +2034,49 @@ function boolean.tonumber(b)
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
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
elseif str == "true" then
return true
elseif str == "false" then
return false
+ elseif not tolerant then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
else
- return str
+ return str == "yes" or str == "on" or str == "t"
end
end
string.toboolean = toboolean
+function string.booleanstring(str)
+ if str == nil then
+ return false
+ elseif str == false then
+ return false
+ elseif str == true then
+ return true
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
+ return false
+ elseif str == 0 then
+ return false
+ elseif (tonumber(str) or 0) > 0 then
+ return true
+ else
+ return str == "yes" or str == "on" or str == "t"
+ end
+end
+
function string.is_boolean(str,default)
if type(str) == "string" then
if str == "true" or str == "yes" or str == "on" or str == "t" then
@@ -1986,7 +2167,7 @@ local function nameonly(name)
return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$",""))
end
-local function extname(name,default)
+local function suffixonly(name,default)
return match(name,"^.+%.([^/\\]-)$") or default or ""
end
@@ -1995,11 +2176,16 @@ local function splitname(name)
return n or name, s or ""
end
-file.basename = basename
-file.dirname = dirname
-file.nameonly = nameonly
-file.extname = extname
-file.suffix = extname
+file.basename = basename
+
+file.pathpart = dirname
+file.dirname = dirname
+
+file.nameonly = nameonly
+
+file.suffixonly = suffixonly
+file.extname = suffixonly -- obsolete
+file.suffix = suffixonly
function file.removesuffix(filename)
return (gsub(filename,"%.[%a%d]+$",""))
@@ -2145,6 +2331,11 @@ end
file.isreadable = file.is_readable -- depricated
file.iswritable = file.is_writable -- depricated
+function file.size(name)
+ local a = attributes(name)
+ return a and a.size or 0
+end
+
-- todo: lpeg \\ / .. does not save much
local checkedsplit = string.checkedsplit
@@ -2275,7 +2466,7 @@ end
--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * C(noperiod^1) * -1
---~ function file.extname(name)
+--~ function file.suffixonly(name)
--~ return lpegmatch(pattern,name) or ""
--~ end
@@ -2337,7 +2528,7 @@ end
--~ end
--~ end
---~ local test = file.extname
+--~ local test = file.suffixonly
--~ local test = file.basename
--~ local test = file.dirname
--~ local test = file.addsuffix
@@ -2383,6 +2574,7 @@ local drive = C(R("az","AZ")) * P(":")
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 rest = C(P(1)^0)
drive = drive + Cc("")
path = path + Cc("")
@@ -2391,7 +2583,8 @@ 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)
+local pattern_c = C(drive * path) * C(base * suffix) -- trick: two extra captures
+local pattern_d = path * rest
function file.splitname(str,splitdrive)
if splitdrive then
@@ -2401,6 +2594,10 @@ function file.splitname(str,splitdrive)
end
end
+function file.splitbase(str)
+ return lpegmatch(pattern_d,str) -- returns path, base+suffix
+end
+
function file.nametotable(str,splitdrive) -- returns table
local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
if splitdrive then
@@ -2422,6 +2619,8 @@ function file.nametotable(str,splitdrive) -- returns table
end
end
+-- print(file.splitbase("a/b/c.txt"))
+
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
--
-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
@@ -2468,14 +2667,14 @@ else
io.fileseparator, io.pathseparator = "/" , ":"
end
-function io.loaddata(filename,textmode)
+function io.loaddata(filename,textmode) -- return nil if empty
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
local data = f:read('*all')
f:close()
- return data
- else
- return nil
+ if #data > 0 then
+ return data
+ end
end
end
@@ -2497,6 +2696,45 @@ function io.savedata(filename,data,joiner)
end
end
+function io.loadlines(filename,n) -- return nil if empty
+ local f = io.open(filename,'r')
+ if f then
+ if n then
+ local lines = { }
+ for i=1,n do
+ local line = f:read("*lines")
+ if line then
+ lines[#lines+1] = line
+ else
+ break
+ end
+ end
+ f:close()
+ lines = concat(lines,"\n")
+ if #lines > 0 then
+ return lines
+ end
+ else
+ local line = f:read("*line") or ""
+ assert(f:close())
+ if #line > 0 then
+ return line
+ end
+ end
+ end
+end
+
+function io.loadchunk(filename,n)
+ local f = io.open(filename,'rb')
+ if f then
+ local data = f:read(n or 1024)
+ f:close()
+ if #data > 0 then
+ return data
+ end
+ end
+end
+
function io.exists(filename)
local f = io.open(filename)
if f == nil then
@@ -2802,7 +3040,7 @@ local remapper = {
function resolvers.findfile(name,fileformat)
name = string.gsub(name,"\\","\/")
fileformat = fileformat and string.lower(fileformat)
- local found = kpse.find_file(name,(fileformat and fileformat ~= "" and (remapper[fileformat] or fileformat)) or file.extname(name,"tex"))
+ local found = kpse.find_file(name,(fileformat and fileformat ~= "" and (remapper[fileformat] or fileformat)) or file.suffix(name,"tex"))
if not found or found == "" then
found = kpse.find_file(name,"other text files")
end
@@ -2811,7 +3049,7 @@ end
function resolvers.findbinfile(name,fileformat)
if not fileformat or fileformat == "" then
- fileformat = file.extname(name) -- string.match(name,"%.([^%.]-)$")
+ fileformat = file.suffix(name) -- string.match(name,"%.([^%.]-)$")
end
return resolvers.findfile(name,(fileformat and remapper[fileformat]) or fileformat)
end
@@ -3235,36 +3473,30 @@ if not modules then modules = { } end modules ['font-ini'] = {
license = "see context related readme files"
}
--- basemethods -> can also be in list
--- presetcontext -> defaults
--- hashfeatures -> ctx version
-
--[[ldx--
<p>Not much is happening here.</p>
--ldx]]--
-local lower = string.lower
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+local allocate = utilities.storage.allocate
local report_defining = logs.reporter("fonts","defining")
-fontloader.totable = fontloader.to_table
-
-fonts = fonts or { } -- already defined in context
+fonts = fonts or { }
local fonts = fonts
--- some of these might move to where they are used first:
-
fonts.hashes = { identifiers = allocate() }
+
+fonts.tables = fonts.tables or { }
+fonts.helpers = fonts.helpers or { }
+fonts.tracers = fonts.tracers or { } -- for the moment till we have move to moduledata
+fonts.specifiers = fonts.specifiers or { } -- in format !
+
fonts.analyzers = { } -- not needed here
fonts.readers = { }
-fonts.tables = { }
fonts.definers = { methods = { } }
-fonts.specifiers = fonts.specifiers or { } -- in format !
fonts.loggers = { register = function() end }
-fonts.helpers = { }
-fonts.tracers = { } -- for the moment till we have move to moduledata
+fontloader.totable = fontloader.to_table
end -- closure
@@ -3301,9 +3533,9 @@ local report_defining = logs.reporter("fonts","defining")
--ldx]]--
local fonts = fonts
-local constructors = { }
+local constructors = fonts.constructors or { }
fonts.constructors = constructors
-local handlers = { }
+local handlers = fonts.handlers or { } -- can have preloaded tables
fonts.handlers = handlers
local specifiers = fonts.specifiers
@@ -3630,6 +3862,10 @@ function constructors.scale(tfmdata,specification)
elseif forcedsize > 1000 then -- safeguard
scaledpoints = forcedsize
end
+ targetparameters.mathsize = mathsize -- context specific
+ targetparameters.textsize = textsize -- context specific
+ targetparameters.forcedsize = forcedsize -- context specific
+ targetparameters.extrafactor = extrafactor -- context specific
--
local tounicode = resources.tounicode
local defaultwidth = resources.defaultwidth or 0
@@ -4341,7 +4577,7 @@ setmetatableindex(formats, function(t,k)
t[k] = l
return l
end
- return rawget(t,file.extname(l))
+ return rawget(t,file.suffix(l))
end)
local locations = { }
@@ -4438,19 +4674,31 @@ function constructors.getfeatureaction(what,where,mode,name)
end
end
-function constructors.newfeatures(what)
- local features = handlers[what].features
+function constructors.newhandler(what) -- could be a metatable newindex
+ local handler = handlers[what]
+ if not handler then
+ handler = { }
+ handlers[what] = handler
+ end
+ return handler
+end
+
+function constructors.newfeatures(what) -- could be a metatable newindex
+ local handler = handlers[what]
+ local features = handler.features
if not features then
- local tables = handlers[what].tables -- can be preloaded
+ local tables = handler.tables -- can be preloaded
+ local statistics = handler.statistics -- can be preloaded
features = allocate {
defaults = { },
descriptions = tables and tables.features or { },
+ used = statistics and statistics.usedfeatures or { },
initializers = { base = { }, node = { } },
processors = { base = { }, node = { } },
manipulators = { base = { }, node = { } },
}
features.register = function(specification) return register(features,specification) end
- handlers[what].features = features -- will also become hidden
+ handler.features = features -- will also become hidden
end
return features
end
@@ -4652,17 +4900,17 @@ local format, match, lower = string.format, string.match, string.lower
local tonumber = tonumber
local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match
-local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+local fonts, logs, trackers = fonts, logs, trackers
-local report_otf = logs.reporter("fonts","otf loading")
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
-local fonts = fonts
+local report_otf = logs.reporter("fonts","otf loading")
-local cid = { }
-fonts.cid = cid
+local cid = { }
+fonts.cid = cid
-local cidmap = { }
-local cidmax = 10
+local cidmap = { }
+local cidmax = 10
-- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap
--
@@ -4721,8 +4969,7 @@ local function loadcidfile(filename)
end
end
-cid.loadfile = loadcidfile -- we use the frozen variant
-
+cid.loadfile = loadcidfile -- we use the frozen variant
local template = "%s-%s-%s.cidmap"
local function locate(registry,ordering,supplement)
@@ -4818,18 +5065,20 @@ if not modules then modules = { } end modules ['font-map'] = {
license = "see context related readme files"
}
+local tonumber = tonumber
+
local match, format, find, concat, gsub, lower = string.match, string.format, string.find, table.concat, string.gsub, string.lower
local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match
local utfbyte = utf.byte
-local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end)
+local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end)
local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_unimapping = v end)
local report_fonts = logs.reporter("fonts","loading") -- not otf only
-local fonts = fonts
-local mappings = { }
-fonts.mappings = mappings
+local fonts = fonts
+local mappings = fonts.mappings or { }
+fonts.mappings = mappings
--[[ldx--
<p>Eventually this code will disappear because map files are kind
@@ -4852,7 +5101,7 @@ end
local hex = R("AF","09")
local hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
local hexsix = (hex^1) / function(s) return tonumber(s,16) end
-local dec = (R("09")^1) / tonumber
+local dec = (R("09")^1) / tonumber
local period = P(".")
local unicode = P("uni") * (hexfour * (period + P(-1)) * Cc(false) + Ct(hexfour^1) * Cc(true))
local ucode = P("u") * (hexsix * (period + P(-1)) * Cc(false) + Ct(hexsix ^1) * Cc(true))
@@ -5263,15 +5512,16 @@ if not modules then modules = { } end modules ['font-oti'] = {
local lower = string.lower
-local allocate = utilities.storage.allocate
-
local fonts = fonts
-local otf = { }
-fonts.handlers.otf = otf
+local constructors = fonts.constructors
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otf = constructors.newhandler("otf")
+local otffeatures = constructors.newfeatures("otf")
+local otftables = otf.tables
local registerotffeature = otffeatures.register
+local allocate = utilities.storage.allocate
+
registerotffeature {
name = "features",
description = "initialization of feature handler",
@@ -5280,8 +5530,6 @@ registerotffeature {
-- these are later hooked into node and base initializaters
-local otftables = otf.tables -- not always defined
-
local function setmode(tfmdata,value)
if value then
tfmdata.properties.mode = lower(value)
@@ -6466,7 +6714,7 @@ actions["prepare lookups"] = function(data,filename,raw)
end
-- The reverse handler does a bit redundant splitting but it's seldom
--- seen so we don' tbother too much. We could store the replacement
+-- seen so we don't bother too much. We could store the replacement
-- in the current list (value instead of true) but it makes other code
-- uglier. Maybe some day.
@@ -6484,6 +6732,22 @@ local function t_uncover(splitter,cache,covers)
return result
end
+local function s_uncover(splitter,cache,cover)
+ if cover == "" then
+ return nil
+ else
+ local uncovered = cache[cover]
+ if not uncovered then
+ uncovered = lpegmatch(splitter,cover)
+-- for i=1,#uncovered do
+-- uncovered[i] = { [uncovered[i]] = true }
+-- end
+ cache[cover] = uncovered
+ end
+ return { uncovered }
+ end
+end
+
local function t_hashed(t,cache)
if t then
local ht = { }
@@ -6505,22 +6769,6 @@ local function t_hashed(t,cache)
end
end
-local function s_uncover(splitter,cache,cover)
- if cover == "" then
- return nil
- else
- local uncovered = cache[cover]
- if not uncovered then
- uncovered = lpegmatch(splitter,cover)
- for i=1,#uncovered do
- uncovered[i] = { [uncovered[i]] = true }
- end
- cache[cover] = uncovered
- end
- return uncovered
- end
-end
-
local s_hashed = t_hashed
local function r_uncover(splitter,cache,cover,replacements)
@@ -6545,11 +6793,15 @@ local function r_uncover(splitter,cache,cover,replacements)
end
end
-actions["reorganize lookups"] = function(data,filename,raw)
+actions["reorganize lookups"] = function(data,filename,raw) -- we could check for "" and n == 0
-- we prefer the before lookups in a normal order
if data.lookups then
local splitter = data.helpers.tounicodetable
- local cache, h_cache = { }, { }
+ local t_u_cache = { }
+ local s_u_cache = t_u_cache -- string keys
+ local t_h_cache = { }
+ local s_h_cache = t_h_cache -- table keys (so we could use one cache)
+ local r_u_cache = { } -- maybe shared
for _, lookup in next, data.lookups do
local rules = lookup.rules
if rules then
@@ -6557,15 +6809,15 @@ actions["reorganize lookups"] = function(data,filename,raw)
if format == "class" then
local before_class = lookup.before_class
if before_class then
- before_class = t_uncover(splitter,cache,reversed(before_class))
+ before_class = t_uncover(splitter,t_u_cache,reversed(before_class))
end
local current_class = lookup.current_class
if current_class then
- current_class = t_uncover(splitter,cache,current_class)
+ current_class = t_uncover(splitter,t_u_cache,current_class)
end
local after_class = lookup.after_class
if after_class then
- after_class = t_uncover(splitter,cache,after_class)
+ after_class = t_uncover(splitter,t_u_cache,after_class)
end
for i=1,#rules do
local rule = rules[i]
@@ -6575,7 +6827,7 @@ actions["reorganize lookups"] = function(data,filename,raw)
for i=1,#before do
before[i] = before_class[before[i]] or { }
end
- rule.before = t_hashed(before,h_cache)
+ rule.before = t_hashed(before,t_h_cache)
end
local current = class.current
local lookups = rule.lookups
@@ -6586,14 +6838,14 @@ actions["reorganize lookups"] = function(data,filename,raw)
lookups[i] = false -- e.g. we can have two lookups and one replacement
end
end
- rule.current = t_hashed(current,h_cache)
+ rule.current = t_hashed(current,t_h_cache)
end
local after = class.after
if after then
for i=1,#after do
after[i] = after_class[after[i]] or { }
end
- rule.after = t_hashed(after,h_cache)
+ rule.after = t_hashed(after,t_h_cache)
end
rule.class = nil
end
@@ -6608,18 +6860,18 @@ actions["reorganize lookups"] = function(data,filename,raw)
if coverage then
local before = coverage.before
if before then
- before = t_uncover(splitter,cache,reversed(before))
- rule.before = t_hashed(before,h_cache)
+ before = t_uncover(splitter,t_u_cache,reversed(before))
+ rule.before = t_hashed(before,t_h_cache)
end
local current = coverage.current
if current then
- current = t_uncover(splitter,cache,current)
- rule.current = t_hashed(current,h_cache)
+ current = t_uncover(splitter,t_u_cache,current)
+ rule.current = t_hashed(current,t_h_cache)
end
local after = coverage.after
if after then
- after = t_uncover(splitter,cache,after)
- rule.after = t_hashed(after,h_cache)
+ after = t_uncover(splitter,t_u_cache,after)
+ rule.after = t_hashed(after,t_h_cache)
end
rule.coverage = nil
end
@@ -6631,22 +6883,22 @@ actions["reorganize lookups"] = function(data,filename,raw)
if reversecoverage then
local before = reversecoverage.before
if before then
- before = t_uncover(splitter,cache,reversed(before))
- rule.before = t_hashed(before,h_cache)
+ before = t_uncover(splitter,t_u_cache,reversed(before))
+ rule.before = t_hashed(before,t_h_cache)
end
local current = reversecoverage.current
if current then
- current = t_uncover(splitter,cache,current)
- rule.current = t_hashed(current,h_cache)
+ current = t_uncover(splitter,t_u_cache,current)
+ rule.current = t_hashed(current,t_h_cache)
end
local after = reversecoverage.after
if after then
- after = t_uncover(splitter,cache,after)
- rule.after = t_hashed(after,h_cache)
+ after = t_uncover(splitter,t_u_cache,after)
+ rule.after = t_hashed(after,t_h_cache)
end
local replacements = reversecoverage.replacements
if replacements then
- rule.replacements = r_uncover(splitter,cache,current,replacements)
+ rule.replacements = r_uncover(splitter,r_u_cache,current,replacements)
end
rule.reversecoverage = nil
end
@@ -6657,19 +6909,19 @@ actions["reorganize lookups"] = function(data,filename,raw)
local glyphs = rule.glyphs
if glyphs then
local fore = glyphs.fore
- if fore then
- fore = s_uncover(splitter,cache,fore)
- rule.before = s_hashed(fore,h_cache)
+ if fore and fore ~= "" then
+ fore = s_uncover(splitter,s_u_cache,fore)
+ rule.before = s_hashed(fore,s_h_cache)
end
local back = glyphs.back
if back then
- back = s_uncover(splitter,cache,back)
- rule.after = s_hashed(back,h_cache)
+ back = s_uncover(splitter,s_u_cache,back)
+ rule.after = s_hashed(back,s_h_cache)
end
local names = glyphs.names
if names then
- names = s_uncover(splitter,cache,names)
- rule.current = s_hashed(names,h_cache)
+ names = s_uncover(splitter,s_u_cache,names)
+ rule.current = s_hashed(names,s_h_cache)
end
rule.glyphs = nil
end
@@ -7324,7 +7576,7 @@ local function read_from_otf(specification)
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)
+ fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
end
return tfmdata
end
@@ -7448,26 +7700,27 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring
local lpegmatch = lpeg.match
local utfchar = utf.char
-local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = 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_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
-local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
+local trace_baseinit = false trackers.register("otf.baseinit", function(v) trace_baseinit = 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_ligatures_detail = false trackers.register("otf.ligatures.detail", function(v) trace_ligatures_detail = v end)
+local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
+local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
-local report_prepare = logs.reporter("fonts","otf prepare")
+local report_prepare = logs.reporter("fonts","otf prepare")
-local fonts = fonts
-local otf = fonts.handlers.otf
+local fonts = fonts
+local otf = fonts.handlers.otf
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
+local otffeatures = otf.features
+local registerotffeature = otffeatures.register
-otf.defaultbasealternate = "none" -- first last
+otf.defaultbasealternate = "none" -- first last
-local wildcard = "*"
-local default = "dflt"
+local wildcard = "*"
+local default = "dflt"
local function gref(descriptions,n)
if type(n) == "number" then
@@ -7602,7 +7855,7 @@ local function finalize_ligatures(tfmdata,ligatures)
if ligature then
local unicode, lookupdata = ligature[1], ligature[2]
if trace then
- print("BUILDING",concat(lookupdata," "),unicode)
+ trace_ligatures_detail("building %q into %q",concat(lookupdata," "),unicode)
end
local size = #lookupdata
local firstcode = lookupdata[1] -- [2]
@@ -7615,7 +7868,7 @@ local function finalize_ligatures(tfmdata,ligatures)
if not firstdata then
firstcode = private
if trace then
- print(" DEFINING",firstname,firstcode)
+ trace_ligatures_detail("defining %q as %q",firstname,firstcode)
end
unicodes[firstname] = firstcode
firstdata = { intermediate = true, ligatures = { } }
@@ -7639,7 +7892,7 @@ local function finalize_ligatures(tfmdata,ligatures)
end
end
if trace then
- print("CODES",firstname,firstcode,secondname,secondcode,target)
+ trace_ligatures_detail("codes (%s,%s) + (%s,%s) -> %s",firstname,firstcode,secondname,secondcode,target)
end
local firstligs = firstdata.ligatures
if firstligs then
@@ -8112,7 +8365,6 @@ 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
@@ -8124,27 +8376,16 @@ 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.
+function injections.installnewkern(nk)
+ newkern = nk or newkern
+end
+
local cursives = { }
local marks = { }
local kerns = { }
@@ -8430,16 +8671,13 @@ function injections.handler(head,where,keep)
-- new per 2010-10-06, width adapted per 2010-02-03
-- we used to negate the width of marks because in tfm
-- 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
- -- one is right
+ -- consequence the sign of p.width was changed
local k = wx[p]
if k then
- n.xoffset = p.xoffset + p.width + d[1] - k[2]
+ -- brill roman: A\char"0300 (but ugly anyway)
+ n.xoffset = p.xoffset - p.width + d[1] - k[2] -- was + p.width
else
- -- n.xoffset = p.xoffset + p.width + d[1]
- -- lucida U\char"032F (default+mark)
+ -- lucida: U\char"032F (default+mark)
n.xoffset = p.xoffset - p.width + d[1] -- 01-05-2011
end
else
@@ -8579,6 +8817,371 @@ end -- closure
do -- begin closure to overcome local limits and interference
+if not modules then modules = { } end modules ['font-ota'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (analysing)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- this might become scrp-*.lua
+
+local type, tostring, match, format, concat = type, tostring, string.match, string.format, table.concat
+
+if not trackers then trackers = { register = function() end } end
+
+local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end)
+
+local fonts, nodes, node = fonts, nodes, node
+
+local allocate = utilities.storage.allocate
+
+local otf = fonts.handlers.otf
+
+local analyzers = fonts.analyzers
+local initializers = allocate()
+local methods = allocate()
+
+analyzers.initializers = initializers
+analyzers.methods = methods
+analyzers.useunicodemarks = false
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+
+local set_attribute = node.set_attribute
+local has_attribute = node.has_attribute
+local traverse_id = node.traverse_id
+local traverse_node_list = node.traverse
+
+local fontdata = fonts.hashes.identifiers
+local state = attributes.private('state')
+local categories = characters and characters.categories or { } -- sorry, only in context
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+--[[ldx--
+<p>Analyzers run per script and/or language and are needed in order to
+process features right.</p>
+--ldx]]--
+
+analyzers.constants = {
+ init = 1,
+ medi = 2,
+ fina = 3,
+ isol = 4,
+ -- devanagari
+ rphf = 5,
+ half = 6,
+ pref = 7,
+ blwf = 8,
+ pstf = 9,
+}
+
+-- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
+-- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace
+
+function analyzers.setstate(head,font)
+ local useunicodemarks = analyzers.useunicodemarks
+ local tfmdata = fontdata[font]
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean
+ while current do
+ local id = current.id
+ if id == glyph_code and current.font == font then
+ local char = current.char
+ local d = descriptions[char]
+ if d then
+ if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then
+ done = true
+ set_attribute(current,state,5) -- mark
+ elseif n == 0 then
+ first, last, n = current, current, 1
+ set_attribute(current,state,1) -- init
+ else
+ last, n = current, n+1
+ set_attribute(current,state,2) -- medi
+ end
+ else -- finish
+ if first and first == last then
+ set_attribute(last,state,4) -- isol
+ elseif last then
+ set_attribute(last,state,3) -- fina
+ end
+ first, last, n = nil, nil, 0
+ end
+ elseif id == disc_code then
+ -- always in the middle
+ set_attribute(current,state,2) -- midi
+ last = current
+ else -- finish
+ if first and first == last then
+ set_attribute(last,state,4) -- isol
+ elseif last then
+ set_attribute(last,state,3) -- fina
+ end
+ first, last, n = nil, nil, 0
+ end
+ current = current.next
+ end
+ if first and first == last then
+ set_attribute(last,state,4) -- isol
+ elseif last then
+ set_attribute(last,state,3) -- fina
+ end
+ return head, done
+end
+
+-- in the future we will use language/script attributes instead of the
+-- font related value, but then we also need dynamic features which is
+-- somewhat slower; and .. we need a chain of them
+
+local function analyzeinitializer(tfmdata,value) -- attr
+ local script, language = otf.scriptandlanguage(tfmdata) -- attr
+ local action = initializers[script]
+ if not action then
+ -- skip
+ elseif type(action) == "function" then
+ return action(tfmdata,value)
+ else
+ local action = action[language]
+ if action then
+ return action(tfmdata,value)
+ end
+ end
+end
+
+local function analyzeprocessor(head,font,attr)
+ local tfmdata = fontdata[font]
+ local script, language = otf.scriptandlanguage(tfmdata,attr)
+ local action = methods[script]
+ if not action then
+ -- skip
+ elseif type(action) == "function" then
+ return action(head,font,attr)
+ else
+ action = action[language]
+ if action then
+ return action(head,font,attr)
+ end
+ end
+ return head, false
+end
+
+registerotffeature {
+ name = "analyze",
+ description = "analysis of (for instance) character classes",
+ default = true,
+ initializers = {
+ node = analyzeinitializer,
+ },
+ processors = {
+ position = 1,
+ node = analyzeprocessor,
+ }
+}
+
+-- latin
+
+methods.latn = analyzers.setstate
+
+-- this info eventually will go into char-def and we will have a state
+-- table for generic then
+
+local zwnj = 0x200C
+local zwj = 0x200D
+
+local isol = {
+ [0x0600] = true, [0x0601] = true, [0x0602] = true, [0x0603] = true,
+ [0x0608] = true, [0x060B] = true, [0x0621] = true, [0x0674] = true,
+ [0x06DD] = true, [zwnj] = true,
+}
+
+local isol_fina = {
+ [0x0622] = true, [0x0623] = true, [0x0624] = true, [0x0625] = true,
+ [0x0627] = true, [0x0629] = true, [0x062F] = true, [0x0630] = true,
+ [0x0631] = true, [0x0632] = true, [0x0648] = true, [0x0671] = true,
+ [0x0672] = true, [0x0673] = true, [0x0675] = true, [0x0676] = true,
+ [0x0677] = true, [0x0688] = true, [0x0689] = true, [0x068A] = true,
+ [0x068B] = true, [0x068C] = true, [0x068D] = true, [0x068E] = true,
+ [0x068F] = true, [0x0690] = true, [0x0691] = true, [0x0692] = true,
+ [0x0693] = true, [0x0694] = true, [0x0695] = true, [0x0696] = true,
+ [0x0697] = true, [0x0698] = true, [0x0699] = true, [0x06C0] = true,
+ [0x06C3] = true, [0x06C4] = true, [0x06C5] = true, [0x06C6] = true,
+ [0x06C7] = true, [0x06C8] = true, [0x06C9] = true, [0x06CA] = true,
+ [0x06CB] = true, [0x06CD] = true, [0x06CF] = true, [0x06D2] = true,
+ [0x06D3] = true, [0x06D5] = true, [0x06EE] = true, [0x06EF] = true,
+ [0x0759] = true, [0x075A] = true, [0x075B] = true, [0x076B] = true,
+ [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 = {
+ [0x0626] = true, [0x0628] = true, [0x062A] = true, [0x062B] = true,
+ [0x062C] = true, [0x062D] = true, [0x062E] = true, [0x0633] = true,
+ [0x0634] = true, [0x0635] = true, [0x0636] = true, [0x0637] = true,
+ [0x0638] = true, [0x0639] = true, [0x063A] = true, [0x063B] = true,
+ [0x063C] = true, [0x063D] = true, [0x063E] = true, [0x063F] = true,
+ [0x0640] = true, [0x0641] = true, [0x0642] = true, [0x0643] = true,
+ [0x0644] = true, [0x0645] = true, [0x0646] = true, [0x0647] = true,
+ [0x0649] = true, [0x064A] = true, [0x066E] = true, [0x066F] = true,
+ [0x0678] = true, [0x0679] = true, [0x067A] = true, [0x067B] = true,
+ [0x067C] = true, [0x067D] = true, [0x067E] = true, [0x067F] = true,
+ [0x0680] = true, [0x0681] = true, [0x0682] = true, [0x0683] = true,
+ [0x0684] = true, [0x0685] = true, [0x0686] = true, [0x0687] = true,
+ [0x069A] = true, [0x069B] = true, [0x069C] = true, [0x069D] = true,
+ [0x069E] = true, [0x069F] = true, [0x06A0] = true, [0x06A1] = true,
+ [0x06A2] = true, [0x06A3] = true, [0x06A4] = true, [0x06A5] = true,
+ [0x06A6] = true, [0x06A7] = true, [0x06A8] = true, [0x06A9] = true,
+ [0x06AA] = true, [0x06AB] = true, [0x06AC] = true, [0x06AD] = true,
+ [0x06AE] = true, [0x06AF] = true, [0x06B0] = true, [0x06B1] = true,
+ [0x06B2] = true, [0x06B3] = true, [0x06B4] = true, [0x06B5] = true,
+ [0x06B6] = true, [0x06B7] = true, [0x06B8] = true, [0x06B9] = true,
+ [0x06BA] = true, [0x06BB] = true, [0x06BC] = true, [0x06BD] = true,
+ [0x06BE] = true, [0x06BF] = true, [0x06C1] = true, [0x06C2] = true,
+ [0x06CC] = true, [0x06CE] = true, [0x06D0] = true, [0x06D1] = true,
+ [0x06FA] = true, [0x06FB] = true, [0x06FC] = true, [0x06FF] = true,
+ [0x0750] = true, [0x0751] = true, [0x0752] = true, [0x0753] = true,
+ [0x0754] = true, [0x0755] = true, [0x0756] = true, [0x0757] = true,
+ [0x0758] = true, [0x075C] = true, [0x075D] = true, [0x075E] = true,
+ [0x075F] = true, [0x0760] = true, [0x0761] = true, [0x0762] = true,
+ [0x0763] = true, [0x0764] = true, [0x0765] = true, [0x0766] = true,
+ [0x0767] = true, [0x0768] = true, [0x0769] = true, [0x076A] = true,
+ [0x076D] = true, [0x076E] = true, [0x076F] = true, [0x0770] = true,
+ [0x0772] = true, [0x0775] = true, [0x0776] = true, [0x0777] = true,
+ [0x077A] = true, [0x077B] = true, [0x077C] = true, [0x077D] = true,
+ [0x077E] = true, [0x077F] = 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,
+ [0x0724] = true, [0x0725] = true, [0x0726] = true, [0x0727] = true,
+ [0x0729] = true, [0x072B] = true,
+
+ -- also
+
+ [zwj] = true,
+}
+
+local arab_warned = { }
+
+-- todo: gref
+
+local function warning(current,what)
+ local char = current.char
+ if not arab_warned[char] then
+ log.report("analyze","arab: character %s (U+%05X) has no %s class", char, char, what)
+ arab_warned[char] = true
+ end
+end
+
+local function finish(first,last)
+ if last then
+ if first == last then
+ local fc = first.char
+ if isol_fina_medi_init[fc] or isol_fina[fc] then
+ set_attribute(first,state,4) -- isol
+ else
+ warning(first,"isol")
+ set_attribute(first,state,0) -- error
+ end
+ else
+ local lc = last.char
+ if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ?
+ -- if laststate == 1 or laststate == 2 or laststate == 4 then
+ set_attribute(last,state,3) -- fina
+ else
+ warning(last,"fina")
+ set_attribute(last,state,0) -- error
+ end
+ end
+ first, last = nil, nil
+ elseif first then
+ -- first and last are either both set so we never com here
+ local fc = first.char
+ if isol_fina_medi_init[fc] or isol_fina[fc] then
+ set_attribute(first,state,4) -- isol
+ else
+ warning(first,"isol")
+ set_attribute(first,state,0) -- error
+ end
+ first = nil
+ end
+ return first, last
+end
+
+function methods.arab(head,font,attr) -- maybe make a special version with no trace
+ local useunicodemarks = analyzers.useunicodemarks
+ local tfmdata = fontdata[font]
+ local marks = tfmdata.resources.marks
+ local first, last, current, done = nil, nil, head, false
+ while current do
+ if current.id == glyph_code and current.subtype<256 and current.font == font and not has_attribute(current,state) then
+ done = true
+ local char = current.char
+ if marks[char] or (useunicodemarks and categories[char] == "mn") then
+ set_attribute(current,state,5) -- mark
+ elseif isol[char] then -- can be zwj or zwnj too
+ first, last = finish(first,last)
+ set_attribute(current,state,4) -- isol
+ first, last = nil, nil
+ elseif not first then
+ if isol_fina_medi_init[char] then
+ set_attribute(current,state,1) -- init
+ first, last = first or current, current
+ elseif isol_fina[char] then
+ set_attribute(current,state,4) -- isol
+ first, last = nil, nil
+ else -- no arab
+ first, last = finish(first,last)
+ end
+ elseif isol_fina_medi_init[char] then
+ first, last = first or current, current
+ set_attribute(current,state,2) -- medi
+ elseif isol_fina[char] then
+ if not has_attribute(last,state,1) then
+ -- tricky, we need to check what last may be !
+ set_attribute(last,state,2) -- medi
+ end
+ set_attribute(current,state,3) -- fina
+ first, last = nil, nil
+ elseif char >= 0x0600 and char <= 0x06FF then
+ set_attribute(current,state,6) -- rest
+ first, last = finish(first,last)
+ else --no
+ first, last = finish(first,last)
+ end
+ else
+ first, last = finish(first,last)
+ end
+ current = current.next
+ end
+ first, last = finish(first,last)
+ return head, done
+end
+
+methods.syrc = methods.arab
+
+directives.register("otf.analyze.useunicodemarks",function(v)
+ analyzers.useunicodemarks = v
+end)
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
if not modules then modules = { } end modules ['font-otn'] = {
version = 1.001,
comment = "companion to font-ini.mkiv",
@@ -8697,6 +9300,8 @@ results in different tables.</p>
-- we now use only one hash. If needed we can have multiple again but in that
-- case I will probably prefix (i.e. rename) the lookups in the cached font file.
+-- Todo: make plugin feature that operates on char/glyphnode arrays
+
local concat, insert, remove = table.concat, table.insert, table.remove
local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring = type, next, tonumber, tostring
@@ -8732,6 +9337,7 @@ local report_subchain = logs.reporter("fonts","otf subchain")
local report_chain = logs.reporter("fonts","otf chain")
local report_process = logs.reporter("fonts","otf process")
local report_prepare = logs.reporter("fonts","otf prepare")
+local report_warning = logs.reporter("fonts","otf warning")
registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
@@ -8891,105 +9497,229 @@ local function pref(kind,lookupname)
return format("feature %s, lookup %s",kind,lookupname)
end
--- we can assume that languages that use marks are not hyphenated
--- we can also assume that at most one discretionary is present
+-- We can assume that languages that use marks are not hyphenated. We can also assume
+-- that at most one discretionary is present.
-local function markstoligature(kind,lookupname,start,stop,char)
- local n = copy_node(start)
- local keep = start
- local current
- current, start = insert_node_after(start,start,n)
- local snext = stop.next
- current.next = snext
- if snext then
- snext.prev = current
+-- 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. Also, later on copying and freeing becomes easier.
+-- However, for arabic we need to keep them around for the sake of mark placement
+-- and indices.
+
+local function copy_glyph(g) -- next and prev are untouched !
+ local components = g.components
+ if components then
+ g.components = nil
+ local n = copy_node(g)
+ g.components = components
+ return n
+ else
+ return copy_node(g)
end
- start.prev, stop.next = nil, nil
- current.char, current.subtype, current.components = char, ligature_code, start
- return keep
end
-local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
- if start == stop then
- start.char = char
+-- start is a mark and we need to keep that one
+
+-- local function markstoligature(kind,lookupname,start,stop,char)
+-- -- [start]..[stop]
+-- local keep = start
+-- local prev = start.prev
+-- local next = stop.next
+-- local base = copy_glyph(start)
+-- local current, start = insert_node_after(start,start,base)
+-- -- [current][start]..[stop]
+-- current.next = next
+-- if next then
+-- next.prev = current
+-- end
+-- start.prev = nil
+-- stop.next = nil
+-- current.char = char
+-- current.subtype = ligature_code
+-- current.components = start
+-- return keep
+-- end
+
+local function markstoligature(kind,lookupname,start,stop,char)
+ if start == stop and start.char == char then
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 = start.font
- lignode.char = char
- lignode.subtype = ligature_code
- local next = stop.next
+ else
local prev = start.prev
- stop.next = nil
+ local next = stop.next
start.prev = nil
- lignode.components = start
- -- print("lignode",nodes.tosequence(lignode))
- -- print("components",nodes.tosequence(lignode.components))
- prev.next = lignode
+ stop.next = nil
+ local base = copy_glyph(start)
+ base.char = char
+ base.subtype = ligature_code
+ base.components = start
+ if prev then
+ prev.next = base
+ end
if next then
- next.prev = lignode
+ next.prev = base
end
- lignode.next = next
- lignode.prev = prev
- -- print("start->end",nodes.tosequence(start))
- return lignode
+ base.next = next
+ base.prev = prev
+ return base
+ end
+end
+
+-- The next code is somewhat complicated by the fact that some fonts can have ligatures made
+-- from ligatures that themselves have marks. This was identified by Kai in for instance
+-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes
+-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next
+-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
+-- third component.
+
+local function getcomponentindex(start)
+ if start.id ~= glyph_code then
+ return 0
+ elseif start.subtype == ligature_code then
+ local i = 0
+ local components = start.components
+ while components do
+ i = i + getcomponentindex(components)
+ components = components.next
+ end
+ return i
+ elseif not marks[start.char] then
+ return 1
else
- -- start is the ligature
+ return 0
+ end
+end
+
+-- local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
+-- if start == stop and start.char == char then
+-- start.char = char
+-- return start
+-- elseif discfound then
+-- local prev = start.prev
+-- local next = stop.next
+-- start.prev = nil
+-- stop.next = nil
+-- local base = copy_glyph(start)
+-- base.char = char
+-- base.subtype = ligature_code
+-- base.components = start -- start can have components
+-- if prev then
+-- prev.next = base
+-- end
+-- if next then
+-- next.prev = base
+-- end
+-- base.next = next
+-- base.prev = prev
+-- return base
+-- else
+-- -- start is the ligature
+-- local deletemarks = markflag ~= "mark"
+-- local prev = start.prev
+-- local next = stop.next
+-- local base = copy_glyph(start)
+-- local current, start = insert_node_after(start,start,base)
+-- -- [start->current][copyofstart->start]...[stop]
+-- current.next = next
+-- if next then
+-- next.prev = current
+-- end
+-- start.prev = nil
+-- stop.next = nil
+-- current.char = char
+-- current.subtype = ligature_code
+-- current.components = start
+-- local head = current
+-- -- this is messy ... we should get rid of the components eventually
+-- local baseindex = 0
+-- local componentindex = 0
+-- while start do
+-- local char = start.char
+-- if not marks[char] then
+-- baseindex = baseindex + componentindex
+-- componentindex = getcomponentindex(start)
+-- elseif not deletemarks then -- quite fishy
+-- set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex))
+-- if trace_marks then
+-- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp))
+-- end
+-- head, current = insert_node_after(head,current,copy_glyph(start)) -- unlikely that mark has components
+-- end
+-- start = start.next
+-- end
+-- start = current.next
+-- while start and start.id == glyph_code do -- hm, is id test needed ?
+-- local char = start.char
+-- if marks[char] then
+-- set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex))
+-- if trace_marks then
+-- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp))
+-- end
+-- else
+-- break
+-- end
+-- start = start.next
+-- end
+-- return head
+-- end
+-- end
+
+local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
+ if start == stop and start.char == char then
+ start.char = char
+ return start
+ end
+ local prev = start.prev
+ local next = stop.next
+ start.prev = nil
+ stop.next = nil
+ local base = copy_glyph(start)
+ base.char = char
+ base.subtype = ligature_code
+ base.components = start -- start can have components
+ if prev then
+ prev.next = base
+ end
+ if next then
+ next.prev = base
+ end
+ base.next = next
+ base.prev = prev
+ if not discfound then
local deletemarks = markflag ~= "mark"
- local n = copy_node(start)
- local current
- current, start = insert_node_after(start,start,n)
- local snext = stop.next
- current.next = snext
- if snext then
- snext.prev = current
- end
- start.prev = nil
- stop.next = nil
- current.char = char
- current.subtype = ligature_code
- current.components = start
- local head = current
- -- this is messy ... we should get rid of the components eventually
- local i = 0 -- is index of base
+ local components = start
+ local baseindex = 0
+ local componentindex = 0
+ local head = base
+ local current = base
while start do
- if not marks[start.char] then
- i = i + 1
+ local char = start.char
+ if not marks[char] then
+ baseindex = baseindex + componentindex
+ componentindex = getcomponentindex(start)
elseif not deletemarks then -- quite fishy
- set_attribute(start,ligacomp,i)
+ set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex))
if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp))
end
- head, current = insert_node_after(head,current,copy_node(start))
+ head, current = insert_node_after(head,current,copy_node(start)) -- unlikely that mark has components
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)
+ local start = components
+ while start and start.id == glyph_code do -- hm, is id test needed ?
+ local char = start.char
+ if marks[char] then
+ set_attribute(start,ligacomp,baseindex + (has_attribute(start,ligacomp) or componentindex))
if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),has_attribute(start,ligacomp))
end
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 base
end
function handlers.gsub_single(start,kind,lookupname,replacement)
@@ -9044,7 +9774,7 @@ local function multiple_glyphs(start,multiple) -- marks ?
if nofmultiples > 1 then
local sn = start.next
for k=2,nofmultiples do -- todo: use insert_node
- local n = copy_node(start)
+ local n = copy_node(start) -- ignore components
n.char = multiple[k]
n.next = sn
n.prev = start
@@ -9069,12 +9799,12 @@ function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence)
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)
+ logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.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))
+ logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(start.char))
end
end
return start, true
@@ -9568,6 +10298,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start
repeat -- start x x m x x stop => start m
local next = start.next
if not marks[next.char] then
+local components = next.components
+if components then -- probably not needed
+ flush_node_list(components)
+end
delete_node(start,next)
end
n = n + 1
@@ -9575,6 +10309,10 @@ local function delete_till_stop(start,stop,ignoremarks) -- keeps start
else -- start x x x stop => start
repeat
local next = start.next
+local components = next.components
+if components then -- probably not needed
+ flush_node_list(components)
+end
delete_node(start,next)
n = n + 1
until next == stop
@@ -10303,7 +11041,7 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
break
end
prev = prev.prev
- elseif seq[n][32] then -- somehat special, as zapfino can have many preceding spaces
+ elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
n = n -1
else
match = false
@@ -10543,12 +11281,7 @@ end)
-- fonts.hashes.lookups = lookuphashes
-local special_attributes = {
- init = 1,
- medi = 2,
- fina = 3,
- isol = 4
-}
+local constants = fonts.analyzers.constants
local function initialize(sequence,script,language,enabled)
local features = sequence.features
@@ -10558,7 +11291,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, sequence }
+ return { valid, constants[kind] or false, sequence.chain or 0, kind, sequence }
end
end
end
@@ -10566,7 +11299,7 @@ local function initialize(sequence,script,language,enabled)
return false
end
-function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in context
+function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
local shared = tfmdata.shared
local properties = tfmdata.properties
local language = properties.language or "dflt"
@@ -10584,12 +11317,17 @@ function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in c
end
local rl = rs[language]
if not rl then
- rl = { }
+ rl = {
+ -- indexed but we can also add specific data by key
+ }
rs[language] = rl
+ local sequences = tfmdata.resources.sequences
setmetatableindex(rl, function(t,k)
- local v = enabled and initialize(sequences[k],script,language,enabled)
- t[k] = v
- return v
+ if type(k) == "number" then
+ local v = enabled and initialize(sequences[k],script,language,enabled)
+ t[k] = v
+ return v
+ end
end)
end
return rl
@@ -10611,6 +11349,8 @@ end
-- start = start.next
-- end
+-- there will be a new direction parser (pre-parsed etc)
+
local function featuresprocessor(head,font,attr)
local lookuphash = lookuphashes[font] -- we can also check sequences here
@@ -10638,7 +11378,7 @@ local function featuresprocessor(head,font,attr)
local sequences = resources.sequences
local done = false
- local datasets = otf.dataset(tfmdata,sequences,font,attr)
+ local datasets = otf.dataset(tfmdata,font,attr)
local dirstack = { } -- could move outside function
@@ -10647,6 +11387,9 @@ local function featuresprocessor(head,font,attr)
-- 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.
+ -- Keeping track of the headnode is needed for devanagari (I generalized it a bit
+ -- so that multiple cases are also covered.
+
for s=1,#sequences do
local dataset = datasets[s]
if dataset then
@@ -10682,8 +11425,12 @@ local function featuresprocessor(head,font,attr)
if lookupcache then
local lookupmatch = lookupcache[start.char]
if lookupmatch then
+ local headnode = start == head
start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
if success then
+ if headnode then
+ head = start
+ end
break
end
end
@@ -10727,10 +11474,14 @@ local function featuresprocessor(head,font,attr)
local lookupmatch = lookupcache[start.char]
if lookupmatch then
-- sequence kan weg
+ local headnode = start == head
local ok
start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
if ok then
success = true
+ if headnode then
+ head = start
+ end
end
end
if start then start = start.next end
@@ -10800,10 +11551,14 @@ local function featuresprocessor(head,font,attr)
local lookupmatch = lookupcache[start.char]
if lookupmatch then
-- we could move all code inline but that makes things even more unreadable
+ local headnode = start == head
local ok
start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
if ok then
success = true
+ if headnode then
+ head = start
+ end
break
end
end
@@ -11130,6 +11885,10 @@ registerotffeature {
}
}
+-- this will change but is needed for an experiment:
+
+otf.handlers = handlers
+
end -- closure
do -- begin closure to overcome local limits and interference
@@ -11757,388 +12516,6 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules = { } end modules ['font-ota'] = {
- version = 1.001,
- comment = "companion to font-otf.lua (analysing)",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- this might become scrp-*.lua
-
-local type, tostring, match, format, concat = type, tostring, string.match, string.format, table.concat
-
-if not trackers then trackers = { register = function() end } end
-
-local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end)
-
-local fonts, nodes, node = fonts, nodes, node
-
-local allocate = utilities.storage.allocate
-
-local otf = fonts.handlers.otf
-
-local analyzers = fonts.analyzers
-local initializers = allocate()
-local methods = allocate()
-
-analyzers.initializers = initializers
-analyzers.methods = methods
-analyzers.useunicodemarks = false
-
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
-
-local set_attribute = node.set_attribute
-local has_attribute = node.has_attribute
-local traverse_id = node.traverse_id
-local traverse_node_list = node.traverse
-
-local fontdata = fonts.hashes.identifiers
-local state = attributes.private('state')
-local categories = characters and characters.categories or { } -- sorry, only in context
-
-local tracers = nodes.tracers
-local colortracers = tracers and tracers.colors
-local setnodecolor = colortracers and colortracers.set or function() end
-local resetnodecolor = colortracers and colortracers.reset or function() end
-
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
-
---[[ldx--
-<p>Analyzers run per script and/or language and are needed in order to
-process features right.</p>
---ldx]]--
-
--- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
--- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace
-
-local state = attributes.private('state')
-
-function analyzers.setstate(head,font)
- local useunicodemarks = analyzers.useunicodemarks
- local tfmdata = fontdata[font]
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean
- while current do
- local id = current.id
- if id == glyph_code and current.font == font then
- local char = current.char
- local d = descriptions[char]
- if d then
- if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then
- done = true
- set_attribute(current,state,5) -- mark
- elseif n == 0 then
- first, last, n = current, current, 1
- set_attribute(current,state,1) -- init
- else
- last, n = current, n+1
- set_attribute(current,state,2) -- medi
- end
- else -- finish
- if first and first == last then
- set_attribute(last,state,4) -- isol
- elseif last then
- set_attribute(last,state,3) -- fina
- end
- first, last, n = nil, nil, 0
- end
- elseif id == disc_code then
- -- always in the middle
- set_attribute(current,state,2) -- midi
- last = current
- else -- finish
- if first and first == last then
- set_attribute(last,state,4) -- isol
- elseif last then
- set_attribute(last,state,3) -- fina
- end
- first, last, n = nil, nil, 0
- end
- current = current.next
- end
- if first and first == last then
- set_attribute(last,state,4) -- isol
- elseif last then
- set_attribute(last,state,3) -- fina
- end
- return head, done
-end
-
--- in the future we will use language/script attributes instead of the
--- font related value, but then we also need dynamic features which is
--- somewhat slower; and .. we need a chain of them
-
-local function analyzeinitializer(tfmdata,value) -- attr
- local script, language = otf.scriptandlanguage(tfmdata) -- attr
- local action = initializers[script]
- if action then
- if type(action) == "function" then
- return action(tfmdata,value)
- else
- local action = action[language]
- if action then
- return action(tfmdata,value)
- end
- end
- end
-end
-
-local function analyzeprocessor(head,font,attr)
- local tfmdata = fontdata[font]
- local script, language = otf.scriptandlanguage(tfmdata,attr)
- local action = methods[script]
- if action then
- if type(action) == "function" then
- return action(head,font,attr)
- else
- action = action[language]
- if action then
- return action(head,font,attr)
- end
- end
- end
- return head, false
-end
-
-registerotffeature {
- name = "analyze",
- description = "analysis of (for instance) character classes",
- default = true,
- initializers = {
- node = analyzeinitializer,
- },
- processors = {
- position = 1,
- node = analyzeprocessor,
- }
-}
-
--- latin
-
-methods.latn = analyzers.setstate
-
--- this info eventually will go into char-def and we will have a state
--- table for generic then
-
-local zwnj = 0x200C
-local zwj = 0x200D
-
-local isol = {
- [0x0600] = true, [0x0601] = true, [0x0602] = true, [0x0603] = true,
- [0x0608] = true, [0x060B] = true, [0x0621] = true, [0x0674] = true,
- [0x06DD] = true, [zwnj] = true,
-}
-
-local isol_fina = {
- [0x0622] = true, [0x0623] = true, [0x0624] = true, [0x0625] = true,
- [0x0627] = true, [0x0629] = true, [0x062F] = true, [0x0630] = true,
- [0x0631] = true, [0x0632] = true, [0x0648] = true, [0x0671] = true,
- [0x0672] = true, [0x0673] = true, [0x0675] = true, [0x0676] = true,
- [0x0677] = true, [0x0688] = true, [0x0689] = true, [0x068A] = true,
- [0x068B] = true, [0x068C] = true, [0x068D] = true, [0x068E] = true,
- [0x068F] = true, [0x0690] = true, [0x0691] = true, [0x0692] = true,
- [0x0693] = true, [0x0694] = true, [0x0695] = true, [0x0696] = true,
- [0x0697] = true, [0x0698] = true, [0x0699] = true, [0x06C0] = true,
- [0x06C3] = true, [0x06C4] = true, [0x06C5] = true, [0x06C6] = true,
- [0x06C7] = true, [0x06C8] = true, [0x06C9] = true, [0x06CA] = true,
- [0x06CB] = true, [0x06CD] = true, [0x06CF] = true, [0x06D2] = true,
- [0x06D3] = true, [0x06D5] = true, [0x06EE] = true, [0x06EF] = true,
- [0x0759] = true, [0x075A] = true, [0x075B] = true, [0x076B] = true,
- [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 = {
- [0x0626] = true, [0x0628] = true, [0x062A] = true, [0x062B] = true,
- [0x062C] = true, [0x062D] = true, [0x062E] = true, [0x0633] = true,
- [0x0634] = true, [0x0635] = true, [0x0636] = true, [0x0637] = true,
- [0x0638] = true, [0x0639] = true, [0x063A] = true, [0x063B] = true,
- [0x063C] = true, [0x063D] = true, [0x063E] = true, [0x063F] = true,
- [0x0640] = true, [0x0641] = true, [0x0642] = true, [0x0643] = true,
- [0x0644] = true, [0x0645] = true, [0x0646] = true, [0x0647] = true,
- [0x0649] = true, [0x064A] = true, [0x066E] = true, [0x066F] = true,
- [0x0678] = true, [0x0679] = true, [0x067A] = true, [0x067B] = true,
- [0x067C] = true, [0x067D] = true, [0x067E] = true, [0x067F] = true,
- [0x0680] = true, [0x0681] = true, [0x0682] = true, [0x0683] = true,
- [0x0684] = true, [0x0685] = true, [0x0686] = true, [0x0687] = true,
- [0x069A] = true, [0x069B] = true, [0x069C] = true, [0x069D] = true,
- [0x069E] = true, [0x069F] = true, [0x06A0] = true, [0x06A1] = true,
- [0x06A2] = true, [0x06A3] = true, [0x06A4] = true, [0x06A5] = true,
- [0x06A6] = true, [0x06A7] = true, [0x06A8] = true, [0x06A9] = true,
- [0x06AA] = true, [0x06AB] = true, [0x06AC] = true, [0x06AD] = true,
- [0x06AE] = true, [0x06AF] = true, [0x06B0] = true, [0x06B1] = true,
- [0x06B2] = true, [0x06B3] = true, [0x06B4] = true, [0x06B5] = true,
- [0x06B6] = true, [0x06B7] = true, [0x06B8] = true, [0x06B9] = true,
- [0x06BA] = true, [0x06BB] = true, [0x06BC] = true, [0x06BD] = true,
- [0x06BE] = true, [0x06BF] = true, [0x06C1] = true, [0x06C2] = true,
- [0x06CC] = true, [0x06CE] = true, [0x06D0] = true, [0x06D1] = true,
- [0x06FA] = true, [0x06FB] = true, [0x06FC] = true, [0x06FF] = true,
- [0x0750] = true, [0x0751] = true, [0x0752] = true, [0x0753] = true,
- [0x0754] = true, [0x0755] = true, [0x0756] = true, [0x0757] = true,
- [0x0758] = true, [0x075C] = true, [0x075D] = true, [0x075E] = true,
- [0x075F] = true, [0x0760] = true, [0x0761] = true, [0x0762] = true,
- [0x0763] = true, [0x0764] = true, [0x0765] = true, [0x0766] = true,
- [0x0767] = true, [0x0768] = true, [0x0769] = true, [0x076A] = true,
- [0x076D] = true, [0x076E] = true, [0x076F] = true, [0x0770] = true,
- [0x0772] = true, [0x0775] = true, [0x0776] = true, [0x0777] = true,
- [0x077A] = true, [0x077B] = true, [0x077C] = true, [0x077D] = true,
- [0x077E] = true, [0x077F] = 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,
- [0x0724] = true, [0x0725] = true, [0x0726] = true, [0x0727] = true,
- [0x0729] = true, [0x072B] = true,
-
- -- also
-
- [zwj] = true,
-}
-
-local arab_warned = { }
-
-
--- todo: gref
-
-local function warning(current,what)
- local char = current.char
- if not arab_warned[char] then
- log.report("analyze","arab: character %s (U+%05X) has no %s class", char, char, what)
- arab_warned[char] = true
- end
-end
-
-function methods.nocolor(head,font,attr)
- for n in traverse_id(glyph_code,head) do
- if not font or n.font == font then
- resetnodecolor(n)
- end
- end
- return head, true
-end
-
-local function finish(first,last)
- if last then
- if first == last then
- local fc = first.char
- if isol_fina_medi_init[fc] or isol_fina[fc] then
- set_attribute(first,state,4) -- isol
- if trace_analyzing then setnodecolor(first,"font:isol") end
- else
- warning(first,"isol")
- set_attribute(first,state,0) -- error
- if trace_analyzing then resetnodecolor(first) end
- end
- else
- local lc = last.char
- if isol_fina_medi_init[lc] or isol_fina[lc] then -- why isol here ?
- -- if laststate == 1 or laststate == 2 or laststate == 4 then
- set_attribute(last,state,3) -- fina
- if trace_analyzing then setnodecolor(last,"font:fina") end
- else
- warning(last,"fina")
- set_attribute(last,state,0) -- error
- if trace_analyzing then resetnodecolor(last) end
- end
- end
- first, last = nil, nil
- elseif first then
- -- first and last are either both set so we never com here
- local fc = first.char
- if isol_fina_medi_init[fc] or isol_fina[fc] then
- set_attribute(first,state,4) -- isol
- if trace_analyzing then setnodecolor(first,"font:isol") end
- else
- warning(first,"isol")
- set_attribute(first,state,0) -- error
- if trace_analyzing then resetnodecolor(first) end
- end
- first = nil
- end
- return first, last
-end
-
-function methods.arab(head,font,attr) -- maybe make a special version with no trace
- local useunicodemarks = analyzers.useunicodemarks
- local tfmdata = fontdata[font]
- local marks = tfmdata.resources.marks
- local first, last, current, done = nil, nil, head, false
- while current do
- if current.id == glyph_code and current.subtype<256 and current.font == font and not has_attribute(current,state) then
- done = true
- local char = current.char
- if marks[char] or (useunicodemarks and categories[char] == "mn") then
- set_attribute(current,state,5) -- mark
- if trace_analyzing then setnodecolor(current,"font:mark") end
- elseif isol[char] then -- can be zwj or zwnj too
- first, last = finish(first,last)
- set_attribute(current,state,4) -- isol
- if trace_analyzing then setnodecolor(current,"font:isol") end
- first, last = nil, nil
- elseif not first then
- if isol_fina_medi_init[char] then
- set_attribute(current,state,1) -- init
- if trace_analyzing then setnodecolor(current,"font:init") end
- first, last = first or current, current
- elseif isol_fina[char] then
- set_attribute(current,state,4) -- isol
- if trace_analyzing then setnodecolor(current,"font:isol") end
- first, last = nil, nil
- else -- no arab
- first, last = finish(first,last)
- end
- elseif isol_fina_medi_init[char] then
- first, last = first or current, current
- set_attribute(current,state,2) -- medi
- if trace_analyzing then setnodecolor(current,"font:medi") end
- elseif isol_fina[char] then
- if not has_attribute(last,state,1) then
- -- tricky, we need to check what last may be !
- set_attribute(last,state,2) -- medi
- if trace_analyzing then setnodecolor(last,"font:medi") end
- end
- set_attribute(current,state,3) -- fina
- if trace_analyzing then setnodecolor(current,"font:fina") end
- first, last = nil, nil
- elseif char >= 0x0600 and char <= 0x06FF then
- if trace_analyzing then setnodecolor(current,"font:rest") end
- first, last = finish(first,last)
- else --no
- first, last = finish(first,last)
- end
- else
- first, last = finish(first,last)
- end
- current = current.next
- end
- first, last = finish(first,last)
- return head, done
-end
-
-methods.syrc = methods.arab
-
-directives.register("otf.analyze.useunicodemarks",function(v)
- analyzers.useunicodemarks = v
-end)
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
if not modules then modules = { } end modules ['luatex-fonts-lua'] = {
version = 1.001,
comment = "companion to luatex-*.tex",
@@ -12185,6 +12562,8 @@ if not modules then modules = { } end modules ['font-def'] = {
license = "see context related readme files"
}
+-- We can overload some of the definers.functions so we don't local them.
+
local concat = table.concat
local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub
local tostring, next = tostring, next
@@ -12221,7 +12600,6 @@ definers.methods = definers.methods or { }
local internalized = allocate() -- internal tex numbers (private)
-
local loadedfonts = constructors.loadedfonts
local designsizes = constructors.designsizes
@@ -12251,7 +12629,7 @@ and prepares a table that will move along as we proceed.</p>
-- name name(sub) name(sub)*spec name*spec
-- name@spec*oeps
-local splitter, splitspecifiers = nil, ""
+local splitter, splitspecifiers = nil, "" -- not so nice
local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc
@@ -12262,7 +12640,7 @@ local space = P(" ")
definers.defaultlookup = "file"
-local prefixpattern = P(false)
+local prefixpattern = P(false)
local function addspecifier(symbol)
splitspecifiers = splitspecifiers .. symbol
@@ -12298,12 +12676,12 @@ function definers.registersplit(symbol,action,verbosename)
end
end
-function definers.makespecification(specification,lookup,name,sub,method,detail,size)
+local function 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",
- specification, (lookup ~= "" and lookup) or "[file]", (name ~= "" and name) or "-",
- (sub ~= "" and sub) or "-", (method ~= "" and method) or "-", (detail ~= "" and detail) or "-")
+ specification, lookup ~= "" and lookup or "[file]", name ~= "" and name or "-",
+ sub ~= "" and sub or "-", method ~= "" and method or "-", detail ~= "" and detail or "-")
end
if not lookup or lookup == "" then
lookup = definers.defaultlookup
@@ -12323,10 +12701,13 @@ function definers.makespecification(specification,lookup,name,sub,method,detail,
return t
end
+
+definers.makespecification = makespecification
+
function definers.analyze(specification, size)
-- can be optimized with locals
local lookup, name, sub, method, detail = getspecification(specification or "")
- return definers.makespecification(specification, lookup, name, sub, method, detail, size)
+ return makespecification(specification, lookup, name, sub, method, detail, size)
end
--[[ldx--
@@ -12373,7 +12754,7 @@ function resolvers.spec(specification)
if resolved then
specification.resolved = resolved
specification.sub = sub
- specification.forced = file.extname(resolved)
+ specification.forced = file.suffix(resolved)
specification.name = file.removesuffix(resolved)
end
else
@@ -12421,12 +12802,13 @@ specification yet.</p>
function definers.applypostprocessors(tfmdata)
local postprocessors = tfmdata.postprocessors
if postprocessors then
+ local properties = tfmdata.properties
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)
+ properties.fullname = format("%s-%s",properties.fullname,extrahash)
end
end
end
@@ -12744,18 +13126,14 @@ local otffeatures = fonts.constructors.newfeatures("otf")
local function initializeitlc(tfmdata,value)
if value then
- -- the magic 40 and it formula come from Dohyun Kim
- local parameters = tfmdata.parameters
+ -- 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.hasitalics = 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
diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua
index f5045a4e3..535519db7 100644
--- a/tex/generic/context/luatex/luatex-fonts.lua
+++ b/tex/generic/context/luatex/luatex-fonts.lua
@@ -176,9 +176,9 @@ else
loadmodule('font-otf.lua')
loadmodule('font-otb.lua')
loadmodule('node-inj.lua') -- will be replaced (luatex >= .70)
+ loadmodule('font-ota.lua')
loadmodule('font-otn.lua')
-- loadmodule('luatex-fonts-chr.lua')
- loadmodule('font-ota.lua')
loadmodule('luatex-fonts-lua.lua')
loadmodule('font-def.lua')
loadmodule('luatex-fonts-def.lua')
diff --git a/tex/generic/context/luatex/luatex-mplib.tex b/tex/generic/context/luatex/luatex-mplib.tex
index ef6dfff95..8af9f2d8a 100644
--- a/tex/generic/context/luatex/luatex-mplib.tex
+++ b/tex/generic/context/luatex/luatex-mplib.tex
@@ -31,8 +31,15 @@
\def\setmplibformat#1{\def\mplibformat{#1}}
\def\setupmplibcatcodes
- {\catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\^=12 \catcode`\~=12
- \catcode`\_=12 \catcode`\%=12 \catcode`\&=12 \catcode`\$=12 }
+ {\catcode`\{=12 % could be optional .. not really needed
+ \catcode`\}=12 % could be optional .. not really needed
+ \catcode`\#=12
+ \catcode`\^=12
+ \catcode`\~=12
+ \catcode`\_=12
+ \catcode`\%=12
+ \catcode`\&=12
+ \catcode`\$=12 }
\def\mplibcode
{\bgroup